Release / Plano (reaproveitar a imagem?) (push) Successful in 12s
CI / Lint e auditorias (push) Successful in 1m39s
CI / Trivy (dependências e segredos) (push) Successful in 13s
CI / Imagem Docker (linux/arm64) (push) Successful in 2m35s
Release / ci (push) Successful in 4m30s
Release / Publica a imagem (linux/arm64) (push) Successful in 19s
Release / Cria a release no Gitea (push) Skipped
Release / Deploy no Coolify (push) Successful in 22s
Sorteia uma placa dos chips da página, com preferência pelas de loja oficial, e troca só pelas setas, com transição suave. Usa o link de afiliado do idioma (rel=sponsored) e some quando o chip não tem placa. Vai nas páginas de série, na comparação e nos dois modos de resultado do seletor. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2793 lines
154 KiB
React
2793 lines
154 KiB
React
"use client";
|
||
|
||
import { useState, useMemo } from "react";
|
||
import { usePathname } from "next/navigation";
|
||
import Header from "@/components/Header";
|
||
import Footer from "@/components/Footer";
|
||
import PlacasSugeridas from "@/components/PlacasSugeridas";
|
||
import Link from "next/link";
|
||
import { getLocalizedHref } from "@/i18n/links";
|
||
import seriesDataPt from "@/public/series.json";
|
||
import seriesDataEn from "@/data/en/series.json";
|
||
import seriesDataEs from "@/data/es/series.json";
|
||
import seriesDataFr from "@/data/fr/series.json";
|
||
import seriesDataDe from "@/data/de/series.json";
|
||
import seriesDataZh from "@/data/zh-CN/series.json";
|
||
import PageHero from "@/components/PageHero";
|
||
import {
|
||
Activity,
|
||
AlertTriangle,
|
||
ArrowRight,
|
||
ArrowUpRight,
|
||
Award,
|
||
Ban,
|
||
Battery,
|
||
BookOpen,
|
||
Bot,
|
||
Cable,
|
||
Check,
|
||
CheckCircle,
|
||
ChevronLeft,
|
||
ChevronRight,
|
||
Cpu,
|
||
Edit2,
|
||
Filter,
|
||
HardDrive,
|
||
HelpCircle,
|
||
Home as HomeIcon,
|
||
KeyRound,
|
||
Layers,
|
||
Lock,
|
||
Monitor,
|
||
Network,
|
||
Radio,
|
||
RotateCcw,
|
||
ShieldCheck,
|
||
ShoppingBag,
|
||
Sliders,
|
||
SlidersHorizontal,
|
||
Sparkles,
|
||
Volume2,
|
||
Wifi,
|
||
Zap,
|
||
} from "lucide-react";
|
||
|
||
// Dynamic icon mapper for options and presets
|
||
const iconMap = {
|
||
// Categorias
|
||
"category_smarthome": <HomeIcon className="h-5 w-5" aria-hidden="true" />,
|
||
"category_multimedia": <Monitor className="h-5 w-5" aria-hidden="true" />,
|
||
"category_ai_edge": <Bot className="h-5 w-5" aria-hidden="true" />,
|
||
"category_wearable": <Battery className="h-5 w-5" aria-hidden="true" />,
|
||
"category_industrial": <Cpu className="h-5 w-5" aria-hidden="true" />,
|
||
"category_basic_iot": <Sparkles className="h-5 w-5" aria-hidden="true" />,
|
||
|
||
// Conectividade
|
||
"connectivity_wifi6_dualband": <Wifi className="h-5 w-5" aria-hidden="true" />,
|
||
"connectivity_wifi6_mesh": <Network className="h-5 w-5" aria-hidden="true" />,
|
||
"connectivity_mesh_only": <Radio className="h-5 w-5" aria-hidden="true" />,
|
||
"connectivity_wifi_ble": <Wifi className="h-5 w-5" aria-hidden="true" />,
|
||
"connectivity_bt_classic_audio": <Volume2 className="h-5 w-5" aria-hidden="true" />,
|
||
"connectivity_ethernet": <Cable className="h-5 w-5" aria-hidden="true" />,
|
||
"connectivity_none_local": <Ban className="h-5 w-5" aria-hidden="true" />,
|
||
|
||
// Alimentação
|
||
"power_battery_critical": <Battery className="h-5 w-5" aria-hidden="true" />,
|
||
"power_ulp_coprocessor": <Activity className="h-5 w-5" aria-hidden="true" />,
|
||
"power_always_on": <Zap className="h-5 w-5" aria-hidden="true" />,
|
||
|
||
// Periféricos / Hardware
|
||
"hardware_mipi_multimedia": <Monitor className="h-5 w-5" aria-hidden="true" />,
|
||
"hardware_usb_otg": <Cable className="h-5 w-5" aria-hidden="true" />,
|
||
"hardware_can_twai": <Sliders className="h-5 w-5" aria-hidden="true" />,
|
||
"hardware_dac_audio": <Volume2 className="h-5 w-5" aria-hidden="true" />,
|
||
"hardware_many_gpios": <SlidersHorizontal className="h-5 w-5" aria-hidden="true" />,
|
||
"hardware_standard_sensors": <Cpu className="h-5 w-5" aria-hidden="true" />,
|
||
|
||
// Memória
|
||
"memory_heavy_psram": <HardDrive className="h-5 w-5" aria-hidden="true" />,
|
||
"memory_moderate_sram": <Layers className="h-5 w-5" aria-hidden="true" />,
|
||
"memory_minimal_cost": <Sparkles className="h-5 w-5" aria-hidden="true" />,
|
||
|
||
// IA
|
||
"ai_ai_vector": <Bot className="h-5 w-5" aria-hidden="true" />,
|
||
"ai_standard": <Ban className="h-5 w-5" aria-hidden="true" />,
|
||
|
||
// Segurança
|
||
"security_key_manager_dpa": <KeyRound className="h-5 w-5" aria-hidden="true" />,
|
||
"security_hardware_ecc_ecdsa": <ShieldCheck className="h-5 w-5" aria-hidden="true" />,
|
||
"security_matter_ecdsa": <ShieldCheck className="h-5 w-5" aria-hidden="true" />,
|
||
"security_secure_boot": <Lock className="h-5 w-5" aria-hidden="true" />,
|
||
"security_standard_tls": <HelpCircle className="h-5 w-5" aria-hidden="true" />,
|
||
|
||
// Ecossistema
|
||
"ecosystem_arduino_ready": <CheckCircle className="h-5 w-5" aria-hidden="true" />,
|
||
"ecosystem_advanced_idf": <Cpu className="h-5 w-5" aria-hidden="true" />,
|
||
};
|
||
|
||
const getOptionIcon = (questionId, value) => {
|
||
const key = `${questionId}_${value}`;
|
||
return iconMap[key] || <HelpCircle className="h-5 w-5" aria-hidden="true" />;
|
||
};
|
||
|
||
// 7 Preset Configurations for 1-click recommendations
|
||
// Valores "sim"/"não" dos dados, nos seis idiomas.
|
||
const VALOR_SIM = ["Sim", "Yes", "Sí", "Oui", "Ja", "是"];
|
||
const ehSim = (v) => VALOR_SIM.includes(v);
|
||
const comecaSim = (v) => VALOR_SIM.some((s) => String(v).startsWith(s));
|
||
const ehNao = (v) => !v || ["Não", "No", "Non", "Nein", "否"].includes(v);
|
||
|
||
const PRESETS_PT = [
|
||
{
|
||
id: "preset_smarthome",
|
||
title: "Smart Home & Matter",
|
||
badge: "Automação 802.15.4",
|
||
description: "Wi-Fi 6, Thread/Zigbee e baixo consumo",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_mesh",
|
||
power: "ulp_coprocessor",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "hardware_ecc_ecdsa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_hmi",
|
||
title: "Painel Touch & Telas",
|
||
badge: "Display / Câmera",
|
||
description: "Display LCD/MIPI, PSRAM e alta taxa de quadros",
|
||
answers: {
|
||
category: "multimedia",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_ai",
|
||
title: "Edge AI & Visão",
|
||
badge: "Aceleração Vetorial",
|
||
description: "Acelerador neural, câmera e alta memória",
|
||
answers: {
|
||
category: "ai_edge",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "ai_vector",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wearable",
|
||
title: "Wearable a Bateria",
|
||
badge: "Deep Sleep <10µA",
|
||
description: "Eficiência extrema e rádio Bluetooth LE",
|
||
answers: {
|
||
category: "wearable",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wifi6_5ghz",
|
||
title: "Wi-Fi 6 Dual-Band (5GHz)",
|
||
badge: "2.4 & 5 GHz",
|
||
description: "Banda de 5 GHz com menor interferência de RF",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_dualband",
|
||
power: "always_on",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "key_manager_dpa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_industrial",
|
||
title: "Industrial / CAN & Rede",
|
||
badge: "Ethernet & TWAI",
|
||
description: "Barramento CAN/TWAI, Ethernet e alta robustez",
|
||
answers: {
|
||
category: "industrial",
|
||
connectivity: "ethernet",
|
||
power: "always_on",
|
||
hardware: "can_twai",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_budget",
|
||
title: "IoT Básico de Baixo Custo",
|
||
badge: "Ultra-Econômico",
|
||
description: "Menor custo por unidade para sensores simples",
|
||
answers: {
|
||
category: "basic_iot",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
}
|
||
];
|
||
|
||
const PRESETS_EN = [
|
||
{
|
||
id: "preset_smarthome",
|
||
title: "Smart Home & Matter",
|
||
badge: "802.15.4 Automation",
|
||
description: "Wi-Fi 6, Thread/Zigbee, and low power",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_mesh",
|
||
power: "ulp_coprocessor",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "hardware_ecc_ecdsa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_hmi",
|
||
title: "Touch Panel & Displays",
|
||
badge: "Display / Camera",
|
||
description: "LCD/MIPI display, PSRAM, and high frame rates",
|
||
answers: {
|
||
category: "multimedia",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_ai",
|
||
title: "Edge AI & Vision",
|
||
badge: "Vector Acceleration",
|
||
description: "Neural accelerator, camera, and large memory",
|
||
answers: {
|
||
category: "ai_edge",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "ai_vector",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wearable",
|
||
title: "Battery-Powered Wearable",
|
||
badge: "Deep Sleep <10µA",
|
||
description: "Extreme efficiency and Bluetooth LE radio",
|
||
answers: {
|
||
category: "wearable",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wifi6_5ghz",
|
||
title: "Dual-Band Wi-Fi 6 (5GHz)",
|
||
badge: "2.4 & 5 GHz",
|
||
description: "5 GHz band with reduced RF interference",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_dualband",
|
||
power: "always_on",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "key_manager_dpa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_industrial",
|
||
title: "Industrial / CAN & Wired Net",
|
||
badge: "Ethernet & TWAI",
|
||
description: "CAN/TWAI bus, Ethernet, and high robustness",
|
||
answers: {
|
||
category: "industrial",
|
||
connectivity: "ethernet",
|
||
power: "always_on",
|
||
hardware: "can_twai",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_budget",
|
||
title: "Entry-Level Low-Cost IoT",
|
||
badge: "Ultra-Budget",
|
||
description: "Lowest unit cost for simple connected sensors",
|
||
answers: {
|
||
category: "basic_iot",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
}
|
||
];
|
||
|
||
|
||
const PRESETS_FR = [
|
||
{
|
||
id: "preset_smarthome",
|
||
title: "Maison connectée et Matter",
|
||
badge: "Automatisation 802.15.4",
|
||
description: "Wi-Fi 6, Thread/Zigbee et basse consommation",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_mesh",
|
||
power: "ulp_coprocessor",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "hardware_ecc_ecdsa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_hmi",
|
||
title: "Écran tactile et affichage",
|
||
badge: "Écran / Caméra",
|
||
description: "Écran LCD/MIPI, PSRAM et haute fréquence d'images",
|
||
answers: {
|
||
category: "multimedia",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_ai",
|
||
title: "IA en périphérie et vision",
|
||
badge: "Accélération vectorielle",
|
||
description: "Accélérateur neuronal, caméra et grande mémoire",
|
||
answers: {
|
||
category: "ai_edge",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "ai_vector",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wearable",
|
||
title: "Appareil portable sur batterie",
|
||
badge: "Deep Sleep <10µA",
|
||
description: "Efficacité extrême et radio Bluetooth LE",
|
||
answers: {
|
||
category: "wearable",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wifi6_5ghz",
|
||
title: "Wi-Fi 6 bi-bande (5GHz)",
|
||
badge: "2.4 et 5 GHz",
|
||
description: "Bande de 5 GHz avec interférences RF réduites",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_dualband",
|
||
power: "always_on",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "key_manager_dpa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_industrial",
|
||
title: "Industriel / CAN et réseau filaire",
|
||
badge: "Ethernet & TWAI",
|
||
description: "Bus CAN/TWAI, Ethernet et haute robustesse",
|
||
answers: {
|
||
category: "industrial",
|
||
connectivity: "ethernet",
|
||
power: "always_on",
|
||
hardware: "can_twai",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_budget",
|
||
title: "IoT de base à faible coût",
|
||
badge: "Économique",
|
||
description: "Coût unitaire minimal pour capteurs connectés simples",
|
||
answers: {
|
||
category: "basic_iot",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
}
|
||
];
|
||
|
||
const PRESETS_DE = [
|
||
{
|
||
id: "preset_smarthome",
|
||
title: "Smart Home und Matter",
|
||
badge: "802.15.4-Automation",
|
||
description: "Wi-Fi 6, Thread/Zigbee und geringer Stromverbrauch",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_mesh",
|
||
power: "ulp_coprocessor",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "hardware_ecc_ecdsa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_hmi",
|
||
title: "Touchpanel und Displays",
|
||
badge: "Display / Kamera",
|
||
description: "LCD/MIPI-Display, PSRAM und hohe Bildwiederholrate",
|
||
answers: {
|
||
category: "multimedia",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_ai",
|
||
title: "Edge-KI und Bildverarbeitung",
|
||
badge: "Vektorbeschleunigung",
|
||
description: "Neuronaler Beschleuniger, Kamera und großer Speicher",
|
||
answers: {
|
||
category: "ai_edge",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "ai_vector",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wearable",
|
||
title: "Batteriebetriebenes Wearable",
|
||
badge: "Deep Sleep <10µA",
|
||
description: "Höchste Effizienz und Bluetooth-LE-Funk",
|
||
answers: {
|
||
category: "wearable",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wifi6_5ghz",
|
||
title: "Dual-Band Wi-Fi 6 (5GHz)",
|
||
badge: "2,4 und 5 GHz",
|
||
description: "5-GHz-Band mit verringerten HF-Interferenzen",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_dualband",
|
||
power: "always_on",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "key_manager_dpa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_industrial",
|
||
title: "Industrie / CAN und Kabelnetzwerk",
|
||
badge: "Ethernet & TWAI",
|
||
description: "CAN/TWAI-Bus, Ethernet und hohe Robustheit",
|
||
answers: {
|
||
category: "industrial",
|
||
connectivity: "ethernet",
|
||
power: "always_on",
|
||
hardware: "can_twai",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_budget",
|
||
title: "Kostengünstiges Basis-IoT",
|
||
badge: "Wirtschaftlich",
|
||
description: "Niedrigste Stückkosten für einfache vernetzte Sensoren",
|
||
answers: {
|
||
category: "basic_iot",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
}
|
||
];
|
||
const PRESETS_ZH = [
|
||
{
|
||
id: "preset_smarthome",
|
||
title: "智能家居与 Matter",
|
||
badge: "802.15.4 自动化",
|
||
description: "Wi-Fi 6、Thread/Zigbee 与低功耗",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_mesh",
|
||
power: "ulp_coprocessor",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "hardware_ecc_ecdsa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_hmi",
|
||
title: "触摸面板与显示屏",
|
||
badge: "显示屏 / 摄像头",
|
||
description: "LCD/MIPI 显示屏、PSRAM 与高帧率",
|
||
answers: {
|
||
category: "multimedia",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_ai",
|
||
title: "边缘 AI 与视觉",
|
||
badge: "向量加速",
|
||
description: "神经网络加速器、摄像头与大内存",
|
||
answers: {
|
||
category: "ai_edge",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "ai_vector",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wearable",
|
||
title: "电池供电的可穿戴设备",
|
||
badge: "深度睡眠 <10µA",
|
||
description: "极致能效与低功耗蓝牙射频",
|
||
answers: {
|
||
category: "wearable",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wifi6_5ghz",
|
||
title: "双频 Wi-Fi 6(5GHz)",
|
||
badge: "2.4 与 5 GHz",
|
||
description: "5 GHz 频段,射频干扰更少",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_dualband",
|
||
power: "always_on",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "key_manager_dpa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_industrial",
|
||
title: "工业 / CAN 与有线网络",
|
||
badge: "以太网与 TWAI",
|
||
description: "CAN/TWAI 总线、以太网与高稳健性",
|
||
answers: {
|
||
category: "industrial",
|
||
connectivity: "ethernet",
|
||
power: "always_on",
|
||
hardware: "can_twai",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_budget",
|
||
title: "入门级低成本物联网",
|
||
badge: "超低预算",
|
||
description: "简单联网传感器的最低单价",
|
||
answers: {
|
||
category: "basic_iot",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
}
|
||
];
|
||
|
||
const PRESETS_ES = [
|
||
{
|
||
id: "preset_smarthome",
|
||
title: "Smart Home y Matter",
|
||
badge: "Automatización 802.15.4",
|
||
description: "Wi-Fi 6, Thread/Zigbee y bajo consumo",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_mesh",
|
||
power: "ulp_coprocessor",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "hardware_ecc_ecdsa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_hmi",
|
||
title: "Panel táctil y pantallas",
|
||
badge: "Pantalla / Cámara",
|
||
description: "Pantalla LCD/MIPI, PSRAM y alta tasa de cuadros",
|
||
answers: {
|
||
category: "multimedia",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_ai",
|
||
title: "Edge AI y visión",
|
||
badge: "Aceleración vectorial",
|
||
description: "Acelerador neuronal, cámara y gran memoria",
|
||
answers: {
|
||
category: "ai_edge",
|
||
connectivity: "wifi_ble",
|
||
power: "always_on",
|
||
hardware: "mipi_multimedia",
|
||
memory: "heavy_psram",
|
||
ai: "ai_vector",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wearable",
|
||
title: "Dispositivo portátil a batería",
|
||
badge: "Deep Sleep <10µA",
|
||
description: "Extrema eficiencia y radio Bluetooth LE",
|
||
answers: {
|
||
category: "wearable",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_wifi6_5ghz",
|
||
title: "Wi-Fi 6 de doble banda (5GHz)",
|
||
badge: "2.4 y 5 GHz",
|
||
description: "Banda de 5 GHz con menor interferencia de RF",
|
||
answers: {
|
||
category: "smarthome",
|
||
connectivity: "wifi6_dualband",
|
||
power: "always_on",
|
||
hardware: "standard_sensors",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "key_manager_dpa",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_industrial",
|
||
title: "Industrial / CAN y red cableada",
|
||
badge: "Ethernet y TWAI",
|
||
description: "Bus CAN/TWAI, Ethernet y alta robustez",
|
||
answers: {
|
||
category: "industrial",
|
||
connectivity: "ethernet",
|
||
power: "always_on",
|
||
hardware: "can_twai",
|
||
memory: "moderate_sram",
|
||
ai: "standard",
|
||
security: "secure_boot",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
},
|
||
{
|
||
id: "preset_budget",
|
||
title: "IoT básico de bajo costo",
|
||
badge: "Económico",
|
||
description: "Menor costo unitario para sensores conectados simples",
|
||
answers: {
|
||
category: "basic_iot",
|
||
connectivity: "wifi_ble",
|
||
power: "battery_critical",
|
||
hardware: "standard_sensors",
|
||
memory: "minimal_cost",
|
||
ai: "standard",
|
||
security: "standard_tls",
|
||
ecosystem: "arduino_ready",
|
||
}
|
||
}
|
||
];
|
||
|
||
const QUESTIONS_PT = [
|
||
{
|
||
id: "category",
|
||
question: "1. Qual é o foco principal ou aplicação do seu projeto?",
|
||
description: "Categorizar sua aplicação ajuda a equilibrar formato físico, custo por unidade, barramentos de mídia e poder computacional.",
|
||
options: [
|
||
{ value: "smarthome", label: "Automação / Smart Home / Dispositivos Conectados", icon: "category_smarthome" },
|
||
{ value: "multimedia", label: "Interfaces Gráficas (Telas LCD/MIPI / Câmeras / IHM)", icon: "category_multimedia" },
|
||
{ value: "ai_edge", label: "Inteligência Artificial na Borda (Visão / Áudio / TinyML)", icon: "category_ai_edge" },
|
||
{ value: "wearable", label: "Dispositivo Portátil / Vestível (Alimentado a Bateria)", icon: "category_wearable" },
|
||
{ value: "industrial", label: "Industrial / Robótica / Redes de Campo e Automação", icon: "category_industrial" },
|
||
{ value: "basic_iot", label: "IoT Básico / Sensor Conectado de Ultra-Baixo Custo", icon: "category_basic_iot" },
|
||
]
|
||
},
|
||
{
|
||
id: "connectivity",
|
||
question: "2. Qual tecnologia de rede sem fio ou cabeada você precisa?",
|
||
description: "O ecossistema ESP32 oferece desde rádios Wi-Fi 6 Dual-Band (2.4/5GHz), Bluetooth 6 e Mesh 802.15.4 até Ethernet cabeada e Bluetooth Clássico.",
|
||
options: [
|
||
{ value: "wifi6_dualband", label: "Wi-Fi 6 Dual-Band (2.4 GHz e 5 GHz) + Bluetooth 6.0", icon: "connectivity_wifi6_dualband" },
|
||
{ value: "wifi6_mesh", label: "Wi-Fi 6 (2.4 GHz) + Matter / Zigbee 3.0 / Thread (802.15.4)", icon: "connectivity_wifi6_mesh" },
|
||
{ value: "mesh_only", label: "Apenas Rádio Mesh (Zigbee / Thread / Matter) + BLE (Sem Wi-Fi)", icon: "connectivity_mesh_only" },
|
||
{ value: "wifi_ble", label: "Wi-Fi 4 Tradicional (2.4 GHz) + Bluetooth LE", icon: "connectivity_wifi_ble" },
|
||
{ value: "bt_classic_audio", label: "Bluetooth Clássico BR/EDR (Áudio A2DP / SPP Serial)", icon: "connectivity_bt_classic_audio" },
|
||
{ value: "ethernet", label: "Rede Cabeada Industrial (Ethernet MAC integrado)", icon: "connectivity_ethernet" },
|
||
{ value: "none_local", label: "Apenas Processamento Local / Sem Conexão Sem Fio", icon: "connectivity_none_local" },
|
||
]
|
||
},
|
||
{
|
||
id: "power",
|
||
question: "3. Como o dispositivo será alimentado eletricamente?",
|
||
description: "A escolha da fonte define a importância de modos de Deep Sleep ultra-baixos (<10µA) e coprocessadores ULP para monitoramento contínuo.",
|
||
options: [
|
||
{ value: "battery_critical", label: "Bateria / Solar (Consumo Ultra-Baixo em Deep Sleep <10µA)", icon: "power_battery_critical" },
|
||
{ value: "ulp_coprocessor", label: "Misto / Monitorar sensores em background via Coprocessador ULP", icon: "power_ulp_coprocessor" },
|
||
{ value: "always_on", label: "Tomada, Fonte Externa ou USB (Sempre Ativo / Alto Desempenho)", icon: "power_always_on" },
|
||
]
|
||
},
|
||
{
|
||
id: "hardware",
|
||
question: "4. Quais periféricos ou barramentos físicos especiais você vai usar?",
|
||
description: "Algumas funcionalidades exigem blocos de silício dedicados, como interfaces de vídeo MIPI/RGB, barramento CAN industrial ou USB nativo.",
|
||
options: [
|
||
{ value: "mipi_multimedia", label: "Display Gráfico LCD (RGB/MIPI DSI) ou Câmeras (DVP/MIPI CSI)", icon: "hardware_mipi_multimedia" },
|
||
{ value: "usb_otg", label: "USB Nativo OTG / Host (Emular teclado/mouse HID, CDC ou modo Host)", icon: "hardware_usb_otg" },
|
||
{ value: "can_twai", label: "Barramento Automotivo / Industrial CAN (TWAI ou CAN-FD)", icon: "hardware_can_twai" },
|
||
{ value: "dac_audio", label: "Áudio Analógico com DAC integrado (saída direta de som)", icon: "hardware_dac_audio" },
|
||
{ value: "many_gpios", label: "Muitos pinos livres de expansão (Mais de 35 GPIOs físicos)", icon: "hardware_many_gpios" },
|
||
{ value: "standard_sensors", label: "Sensores comuns com barramentos tradicionais (I2C, SPI, UART, PWM)", icon: "hardware_standard_sensors" },
|
||
]
|
||
},
|
||
{
|
||
id: "memory",
|
||
question: "5. Qual o volume de memória RAM / PSRAM necessário?",
|
||
description: "Projetos gráficos (LVGL), visão computacional, áudio ou pilhas pesadas exigem suporte a PSRAM externa ou integrada de alta densidade.",
|
||
options: [
|
||
{ value: "heavy_psram", label: "Alta Densidade de PSRAM (>4 MB a 64 MB para buffers de vídeo, IA ou LVGL)", icon: "memory_heavy_psram" },
|
||
{ value: "moderate_sram", label: "SRAM interna equilibrada (320 KB a 512 KB) com ou sem PSRAM leve", icon: "memory_moderate_sram" },
|
||
{ value: "minimal_cost", label: "Memória compacta e econômica (firmware enxuto de baixo custo)", icon: "memory_minimal_cost" },
|
||
]
|
||
},
|
||
{
|
||
id: "ai",
|
||
question: "6. Seu projeto usará Inteligência Artificial local (Edge AI / TinyML)?",
|
||
description: "Instruções vetoriais e aceleradores neurais dedicados em hardware reduzem o tempo de inferência de redes neurais de segundos para milissegundos.",
|
||
options: [
|
||
{ value: "ai_vector", label: "Sim, preciso de acelerador vetorial de IA em hardware (TinyML / Visão)", icon: "ai_ai_vector" },
|
||
{ value: "standard", label: "Não, processamento lógico e matemático comum é suficiente", icon: "ai_standard" },
|
||
]
|
||
},
|
||
{
|
||
id: "security",
|
||
question: "7. Qual nível de segurança e criptografia por hardware o produto exige?",
|
||
description: "As séries diferem em suporte a Key Manager, proteção contra ataques de canal lateral (DPA), curvas elípticas (ECC/ECDSA) e aceleradores AES.",
|
||
options: [
|
||
{ value: "key_manager_dpa", label: "Proteção Máxima: Key Manager em hardware (chave isolada da CPU) e Proteção DPA", icon: "security_key_manager_dpa" },
|
||
{ value: "hardware_ecc_ecdsa", label: "Acelerador de Curvas Elípticas (ECC) e Assinatura Digital ECDSA por hardware", icon: "security_hardware_ecc_ecdsa" },
|
||
{ value: "secure_boot", label: "Boot Seguro V2 e Criptografia de Flash (XTS-AES) contra cópia do firmware", icon: "security_secure_boot" },
|
||
{ value: "standard_tls", label: "Comunicação TLS/HTTPS comum (Aceleradores AES e SHA por hardware)", icon: "security_standard_tls" },
|
||
]
|
||
},
|
||
{
|
||
id: "ecosystem",
|
||
question: "8. Qual é a sua preferência de ambiente de desenvolvimento?",
|
||
description: "Chips mais maduros têm amplo suporte oficial no Arduino Core com centenas de bibliotecas prontas, enquanto chips preliminares utilizam ESP-IDF.",
|
||
options: [
|
||
{ value: "arduino_ready", label: "Pronto para Arduino IDE (suporte maduro com vasta coleção de bibliotecas)", icon: "ecosystem_arduino_ready" },
|
||
{ value: "advanced_idf", label: "ESP-IDF profissional ou aberto a silícios de última geração (S31, H4, etc.)", icon: "ecosystem_advanced_idf" },
|
||
]
|
||
}
|
||
];
|
||
|
||
const QUESTIONS_EN = [
|
||
{
|
||
id: "category",
|
||
question: "1. What is the main focus or application of your project?",
|
||
description: "Categorizing your application helps balance physical form factor, unit cost, media buses, and compute performance.",
|
||
options: [
|
||
{ value: "smarthome", label: "Automation / Smart Home / Connected Devices", icon: "category_smarthome" },
|
||
{ value: "multimedia", label: "Graphical Interfaces (LCD/MIPI Displays / Cameras / HMI)", icon: "category_multimedia" },
|
||
{ value: "ai_edge", label: "Edge Artificial Intelligence (Vision / Audio / TinyML)", icon: "category_ai_edge" },
|
||
{ value: "wearable", label: "Portable / Wearable Device (Battery-Powered)", icon: "category_wearable" },
|
||
{ value: "industrial", label: "Industrial / Robotics / Fieldbuses and Automation", icon: "category_industrial" },
|
||
{ value: "basic_iot", label: "Basic IoT / Ultra-Low-Cost Connected Sensor", icon: "category_basic_iot" },
|
||
]
|
||
},
|
||
{
|
||
id: "connectivity",
|
||
question: "2. Which wireless or wired networking technology do you need?",
|
||
description: "The ESP32 ecosystem offers everything from Dual-Band Wi-Fi 6 (2.4/5GHz), Bluetooth 6, and 802.15.4 Mesh to wired Ethernet and Bluetooth Classic.",
|
||
options: [
|
||
{ value: "wifi6_dualband", label: "Dual-Band Wi-Fi 6 (2.4 GHz & 5 GHz) + Bluetooth 6.0", icon: "connectivity_wifi6_dualband" },
|
||
{ value: "wifi6_mesh", label: "Wi-Fi 6 (2.4 GHz) + Matter / Zigbee 3.0 / Thread (802.15.4)", icon: "connectivity_wifi6_mesh" },
|
||
{ value: "mesh_only", label: "Mesh Radio Only (Zigbee / Thread / Matter) + BLE (No Wi-Fi)", icon: "connectivity_mesh_only" },
|
||
{ value: "wifi_ble", label: "Traditional Wi-Fi 4 (2.4 GHz) + Bluetooth LE", icon: "connectivity_wifi_ble" },
|
||
{ value: "bt_classic_audio", label: "Bluetooth Classic BR/EDR (A2DP Audio / SPP Serial)", icon: "connectivity_bt_classic_audio" },
|
||
{ value: "ethernet", label: "Industrial Wired Network (Integrated Ethernet MAC)", icon: "connectivity_ethernet" },
|
||
{ value: "none_local", label: "Local Processing Only / No Wireless Connection", icon: "connectivity_none_local" },
|
||
]
|
||
},
|
||
{
|
||
id: "power",
|
||
question: "3. How will the device be electrically powered?",
|
||
description: "Power source choices determine the need for ultra-low Deep Sleep modes (<10µA) and ULP coprocessors for continuous monitoring.",
|
||
options: [
|
||
{ value: "battery_critical", label: "Battery / Solar (Ultra-Low Deep Sleep Current <10µA)", icon: "power_battery_critical" },
|
||
{ value: "ulp_coprocessor", label: "Mixed / Background Sensor Monitoring via ULP Coprocessor", icon: "power_ulp_coprocessor" },
|
||
{ value: "always_on", label: "Mains, External Power Supply, or USB (Always-On / High Performance)", icon: "power_always_on" },
|
||
]
|
||
},
|
||
{
|
||
id: "hardware",
|
||
question: "4. Which specialized peripherals or physical buses will you use?",
|
||
description: "Certain features require dedicated silicon blocks, such as MIPI/RGB video interfaces, industrial CAN bus, or native USB.",
|
||
options: [
|
||
{ value: "mipi_multimedia", label: "Graphic LCD Display (RGB/MIPI DSI) or Cameras (DVP/MIPI CSI)", icon: "hardware_mipi_multimedia" },
|
||
{ value: "usb_otg", label: "Native USB OTG / Host (Emulate HID keyboard/mouse, CDC, or Host mode)", icon: "hardware_usb_otg" },
|
||
{ value: "can_twai", label: "Automotive / Industrial CAN Bus (TWAI or CAN-FD)", icon: "hardware_can_twai" },
|
||
{ value: "dac_audio", label: "Analog Audio with Integrated DAC (Direct Sound Output)", icon: "hardware_dac_audio" },
|
||
{ value: "many_gpios", label: "Many Expansion Pins (More than 35 Physical GPIOs)", icon: "hardware_many_gpios" },
|
||
{ value: "standard_sensors", label: "Standard Sensors with Common Buses (I2C, SPI, UART, PWM)", icon: "hardware_standard_sensors" },
|
||
]
|
||
},
|
||
{
|
||
id: "memory",
|
||
question: "5. What volume of RAM / PSRAM is required?",
|
||
description: "Graphic UI projects (LVGL), computer vision, audio, or heavy stacks require high-density external or integrated PSRAM.",
|
||
options: [
|
||
{ value: "heavy_psram", label: "High PSRAM Density (>4 MB to 64 MB for video buffers, AI, or LVGL)", icon: "memory_heavy_psram" },
|
||
{ value: "moderate_sram", label: "Balanced Internal SRAM (320 KB to 512 KB) with or without light PSRAM", icon: "memory_moderate_sram" },
|
||
{ value: "minimal_cost", label: "Compact and Economical Memory (Lean, low-cost firmware)", icon: "memory_minimal_cost" },
|
||
]
|
||
},
|
||
{
|
||
id: "ai",
|
||
question: "6. Will your project use local Artificial Intelligence (Edge AI / TinyML)?",
|
||
description: "Hardware vector instructions and dedicated neural accelerators cut neural network inference times from seconds to milliseconds.",
|
||
options: [
|
||
{ value: "ai_vector", label: "Yes, I need hardware AI vector acceleration (TinyML / Vision)", icon: "ai_ai_vector" },
|
||
{ value: "standard", label: "No, standard logic and mathematical processing is sufficient", icon: "ai_standard" },
|
||
]
|
||
},
|
||
{
|
||
id: "security",
|
||
question: "7. What level of hardware security and cryptography does the product require?",
|
||
description: "Series differ in Key Manager support, side-channel attack protection (DPA), elliptic curves (ECC/ECDSA), and AES accelerators.",
|
||
options: [
|
||
{ value: "key_manager_dpa", label: "Maximum Protection: Hardware Key Manager (isolated from CPU) and DPA Protection", icon: "security_key_manager_dpa" },
|
||
{ value: "hardware_ecc_ecdsa", label: "Hardware Elliptic Curve Accelerator (ECC) and ECDSA Digital Signature", icon: "security_hardware_ecc_ecdsa" },
|
||
{ value: "secure_boot", label: "Secure Boot V2 and Flash Encryption (XTS-AES) against firmware cloning", icon: "security_secure_boot" },
|
||
{ value: "standard_tls", label: "Standard TLS/HTTPS Communication (Hardware AES and SHA accelerators)", icon: "security_standard_tls" },
|
||
]
|
||
},
|
||
{
|
||
id: "ecosystem",
|
||
question: "8. What is your development environment preference?",
|
||
description: "Mature chips offer broad official support in Arduino Core with hundreds of ready libraries, while newer silicon starts in ESP-IDF.",
|
||
options: [
|
||
{ value: "arduino_ready", label: "Arduino IDE Ready (mature support with vast library ecosystem)", icon: "ecosystem_arduino_ready" },
|
||
{ value: "advanced_idf", label: "Professional ESP-IDF or open to next-gen silicon (S31, H4, etc.)", icon: "ecosystem_advanced_idf" },
|
||
]
|
||
}
|
||
];
|
||
|
||
|
||
const QUESTIONS_FR = [
|
||
{
|
||
id: "category",
|
||
question: "1. Quel est l'objectif principal ou l'application de votre projet ?",
|
||
description: "Catégoriser votre application aide à équilibrer format physique, coût unitaire, bus multimédias et puissance de calcul.",
|
||
options: [
|
||
{ value: "smarthome", label: "Domotique / Smart Home / Appareils connectés", icon: "category_smarthome" },
|
||
{ value: "multimedia", label: "Interfaces graphiques (Écrans LCD/MIPI / Caméras / IHM)", icon: "category_multimedia" },
|
||
{ value: "ai_edge", label: "Intelligence artificielle en périphérie (Vision / Audio / TinyML)", icon: "category_ai_edge" },
|
||
{ value: "wearable", label: "Appareil portable / Wearable (Alimenté par batterie)", icon: "category_wearable" },
|
||
{ value: "industrial", label: "Industrie / Robotique / Réseaux de terrain et automatisation", icon: "category_industrial" },
|
||
{ value: "basic_iot", label: "IoT de base / Capteur connecté à ultra-faible coût", icon: "category_basic_iot" },
|
||
]
|
||
},
|
||
{
|
||
id: "connectivity",
|
||
question: "2. De quelle technologie réseau sans fil ou filaire avez-vous besoin ?",
|
||
description: "L'écosystème ESP32 propose du Wi-Fi 6 bi-bande (2,4/5 GHz), Bluetooth 6 et réseaux maillés 802.15.4 jusqu'à l'Ethernet filaire et le Bluetooth classique.",
|
||
options: [
|
||
{ value: "wifi6_dualband", label: "Wi-Fi 6 bi-bande (2,4 GHz et 5 GHz) + Bluetooth 6.0", icon: "connectivity_wifi6_dualband" },
|
||
{ value: "wifi6_mesh", label: "Wi-Fi 6 (2,4 GHz) + Matter / Zigbee 3.0 / Thread (802.15.4)", icon: "connectivity_wifi6_mesh" },
|
||
{ value: "mesh_only", label: "Radio Mesh uniquement (Zigbee / Thread / Matter) + BLE (sans Wi-Fi)", icon: "connectivity_mesh_only" },
|
||
{ value: "wifi_ble", label: "Wi-Fi 4 traditionnel (2,4 GHz) + Bluetooth LE", icon: "connectivity_wifi_ble" },
|
||
{ value: "bt_classic_audio", label: "Bluetooth classique BR/EDR (Audio A2DP / SPP série)", icon: "connectivity_bt_classic_audio" },
|
||
{ value: "ethernet", label: "Réseau filaire industriel (Contrôleur MAC Ethernet intégré)", icon: "connectivity_ethernet" },
|
||
{ value: "none_local", label: "Traitement local uniquement / Sans connexion sans fil", icon: "connectivity_none_local" },
|
||
]
|
||
},
|
||
{
|
||
id: "power",
|
||
question: "3. Comment l'appareil sera-t-il alimenté électriquement ?",
|
||
description: "Le choix de la source d'énergie détermine l'importance des modes Deep Sleep ultra-bas (<10 µA) et des coprocesseurs ULP pour la surveillance continue.",
|
||
options: [
|
||
{ value: "battery_critical", label: "Batterie / Solaire (Consommation ultra-basse en Deep Sleep <10 µA)", icon: "power_battery_critical" },
|
||
{ value: "ulp_coprocessor", label: "Mixte / Surveillance de capteurs en arrière-plan via coprocesseur ULP", icon: "power_ulp_coprocessor" },
|
||
{ value: "always_on", label: "Secteur, alimentation externe ou USB (Toujours actif / Haute performance)", icon: "power_always_on" },
|
||
]
|
||
},
|
||
{
|
||
id: "hardware",
|
||
question: "4. Quels périphériques ou bus matériels spécifiques utiliserez-vous ?",
|
||
description: "Certaines fonctions requièrent des blocs de silicium dédiés, comme les interfaces vidéo MIPI/RGB, le bus CAN industriel ou l'USB natif.",
|
||
options: [
|
||
{ value: "mipi_multimedia", label: "Écran graphique LCD (RGB/MIPI DSI) ou Caméras (DVP/MIPI CSI)", icon: "hardware_mipi_multimedia" },
|
||
{ value: "usb_otg", label: "USB natif OTG / Host (Émulation clavier/souris HID, CDC ou mode Hôte)", icon: "hardware_usb_otg" },
|
||
{ value: "can_twai", label: "Bus automobile / industriel CAN (TWAI ou CAN-FD)", icon: "hardware_can_twai" },
|
||
{ value: "dac_audio", label: "Audio analogique avec DAC intégré (sortie audio directe)", icon: "hardware_dac_audio" },
|
||
{ value: "many_gpios", label: "Nombreuses broches libres d'extension (Plus de 35 GPIO physiques)", icon: "hardware_many_gpios" },
|
||
{ value: "standard_sensors", label: "Capteurs standards avec bus traditionnels (I2C, SPI, UART, PWM)", icon: "hardware_standard_sensors" },
|
||
]
|
||
},
|
||
{
|
||
id: "memory",
|
||
question: "5. Quel volume de mémoire RAM / PSRAM est nécessaire ?",
|
||
description: "Les projets graphiques (LVGL), la vision par ordinateur, l'audio ou les piles lourdes exigent la prise en charge de PSRAM externe ou intégrée haute densité.",
|
||
options: [
|
||
{ value: "heavy_psram", label: "Haute densité de PSRAM (>4 Mo à 64 Mo pour tampons vidéo, IA ou LVGL)", icon: "memory_heavy_psram" },
|
||
{ value: "moderate_sram", label: "SRAM interne équilibrée (320 Ko à 512 Ko) avec ou sans PSRAM légère", icon: "memory_moderate_sram" },
|
||
{ value: "minimal_cost", label: "Mémoire compacte et économique (firmware optimisé à bas coût)", icon: "memory_minimal_cost" },
|
||
]
|
||
},
|
||
{
|
||
id: "ai",
|
||
question: "6. Votre projet utilisera-t-il l'Intelligence Artificielle locale (Edge AI / TinyML) ?",
|
||
description: "Les instructions vectorielles et les accélérateurs neuronaux matériels dédiés réduisent le temps d'inférence des réseaux neuronaux de secondes à millisecondes.",
|
||
options: [
|
||
{ value: "ai_vector", label: "Oui, accélération vectorielle IA matérielle requise (TinyML / Vision)", icon: "ai_ai_vector" },
|
||
{ value: "standard", label: "Non, un traitement logique et mathématique standard suffit", icon: "ai_standard" },
|
||
]
|
||
},
|
||
{
|
||
id: "security",
|
||
question: "7. Quel niveau de sécurité matérielle et de cryptographie le produit requiert-il ?",
|
||
description: "Les séries diffèrent dans la prise en charge du Key Manager, de la protection DPA contre les attaques par canaux auxiliaires, des courbes elliptiques (ECC/ECDSA) et des accélérateurs AES.",
|
||
options: [
|
||
{ value: "key_manager_dpa", label: "Protection maximale : Key Manager matériel (clés isolées du CPU) et protection DPA", icon: "security_key_manager_dpa" },
|
||
{ value: "hardware_ecc_ecdsa", label: "Accélérateur matériel de courbes elliptiques (ECC) et signature ECDSA", icon: "security_hardware_ecc_ecdsa" },
|
||
{ value: "secure_boot", label: "Démarrage sécurisé V2 et chiffrement Flash (XTS-AES) contre le clonage", icon: "security_secure_boot" },
|
||
{ value: "standard_tls", label: "Communication TLS/HTTPS standard (Accélérateurs matériels AES et SHA)", icon: "security_standard_tls" },
|
||
]
|
||
},
|
||
{
|
||
id: "ecosystem",
|
||
question: "8. Quelle est votre préférence pour l'environnement de développement ?",
|
||
description: "Les puces matures bénéficient d'un large support officiel dans l'Arduino Core avec des centaines de bibliothèques prêtes, tandis que les puces préliminaires exploitent l'ESP-IDF.",
|
||
options: [
|
||
{ value: "arduino_ready", label: "Prêt pour Arduino IDE (support mature avec vaste collection de bibliothèques)", icon: "ecosystem_arduino_ready" },
|
||
{ value: "advanced_idf", label: "ESP-IDF professionnel ou ouvert aux composants de nouvelle génération (S31, H4, etc.)", icon: "ecosystem_advanced_idf" },
|
||
]
|
||
}
|
||
];
|
||
|
||
const QUESTIONS_DE = [
|
||
{
|
||
id: "category",
|
||
question: "1. Was ist der Hauptfokus oder die Anwendung Ihres Projekts?",
|
||
description: "Die Kategorisierung Ihrer Anwendung hilft bei der Balance zwischen Bauform, Stückkosten, Medienbussen und Rechenleistung.",
|
||
options: [
|
||
{ value: "smarthome", label: "Automation / Smart Home / Vernetzte Geräte", icon: "category_smarthome" },
|
||
{ value: "multimedia", label: "Grafische Schnittstellen (LCD/MIPI-Displays / Kameras / HMI)", icon: "category_multimedia" },
|
||
{ value: "ai_edge", label: "Künstliche Intelligenz am Edge (Vision / Audio / TinyML)", icon: "category_ai_edge" },
|
||
{ value: "wearable", label: "Tragbares Gerät / Wearable (Batteriebetrieben)", icon: "category_wearable" },
|
||
{ value: "industrial", label: "Industrie / Robotik / Feldbusse und Automation", icon: "category_industrial" },
|
||
{ value: "basic_iot", label: "Basis-IoT / Extrem kostengünstiger vernetzter Sensor", icon: "category_basic_iot" },
|
||
]
|
||
},
|
||
{
|
||
id: "connectivity",
|
||
question: "2. Welche drahtlose oder kabelgebundene Netzwerktechnologie benötigen Sie?",
|
||
description: "Das ESP32-Ökosystem bietet von Dual-Band Wi-Fi 6 (2,4/5 GHz), Bluetooth 6 und 802.15.4 Mesh bis hin zu Ethernet und klassischem Bluetooth alles an.",
|
||
options: [
|
||
{ value: "wifi6_dualband", label: "Dual-Band Wi-Fi 6 (2,4 GHz und 5 GHz) + Bluetooth 6.0", icon: "connectivity_wifi6_dualband" },
|
||
{ value: "wifi6_mesh", label: "Wi-Fi 6 (2,4 GHz) + Matter / Zigbee 3.0 / Thread (802.15.4)", icon: "connectivity_wifi6_mesh" },
|
||
{ value: "mesh_only", label: "Nur Mesh-Funk (Zigbee / Thread / Matter) + BLE (ohne Wi-Fi)", icon: "connectivity_mesh_only" },
|
||
{ value: "wifi_ble", label: "Klassisches Wi-Fi 4 (2,4 GHz) + Bluetooth LE", icon: "connectivity_wifi_ble" },
|
||
{ value: "bt_classic_audio", label: "Klassisches Bluetooth BR/EDR (A2DP-Audio / Serielles SPP)", icon: "connectivity_bt_classic_audio" },
|
||
{ value: "ethernet", label: "Industrielles Kabelnetzwerk (Integrierter Ethernet-MAC-Controller)", icon: "connectivity_ethernet" },
|
||
{ value: "none_local", label: "Nur lokale Verarbeitung / Keine drahtlose Verbindung", icon: "connectivity_none_local" },
|
||
]
|
||
},
|
||
{
|
||
id: "power",
|
||
question: "3. Wie wird das Gerät mit Strom versorgt?",
|
||
description: "Die Wahl der Stromquelle bestimmt die Notwendigkeit von extrem niedrigen Deep-Sleep-Modi (<10 µA) und ULP-Coprozessoren für die permanente Überwachung.",
|
||
options: [
|
||
{ value: "battery_critical", label: "Batterie / Solar (Extrem niedriger Deep-Sleep-Strom <10 µA)", icon: "power_battery_critical" },
|
||
{ value: "ulp_coprocessor", label: "Gemischt / Sensorüberwachung im Hintergrund per ULP-Coprozessor", icon: "power_ulp_coprocessor" },
|
||
{ value: "always_on", label: "Steckdose, externes Netzteil oder USB (Dauerbetrieb / Hohe Leistung)", icon: "power_always_on" },
|
||
]
|
||
},
|
||
{
|
||
id: "hardware",
|
||
question: "4. Welche speziellen Peripheriegeräte oder Busse werden Sie nutzen?",
|
||
description: "Einige Funktionen erfordern dedizierte Siliziumblöcke wie MIPI/RGB-Videoschnittstellen, industriellen CAN-Bus oder natives USB.",
|
||
options: [
|
||
{ value: "mipi_multimedia", label: "Grafisches LCD-Display (RGB/MIPI DSI) oder Kameras (DVP/MIPI CSI)", icon: "hardware_mipi_multimedia" },
|
||
{ value: "usb_otg", label: "Natives USB OTG / Host (HID-Tastatur/Maus-Emulation, CDC oder Host-Modus)", icon: "hardware_usb_otg" },
|
||
{ value: "can_twai", label: "Automobil- / Industrie-CAN-Bus (TWAI oder CAN-FD)", icon: "hardware_can_twai" },
|
||
{ value: "dac_audio", label: "Analoges Audio mit integriertem DAC (direkte Tonausgabe)", icon: "hardware_dac_audio" },
|
||
{ value: "many_gpios", label: "Viele freie Erweiterungspins (Mehr als 35 physische GPIOs)", icon: "hardware_many_gpios" },
|
||
{ value: "standard_sensors", label: "Standardsensoren mit herkömmlichen Bussen (I2C, SPI, UART, PWM)", icon: "hardware_standard_sensors" },
|
||
]
|
||
},
|
||
{
|
||
id: "memory",
|
||
question: "5. Wie viel RAM- / PSRAM-Speicher ist erforderlich?",
|
||
description: "Grafik-UI-Projekte (LVGL), Computer Vision, Audio oder umfangreiche Stacks erfordern hochdichten externen oder integrierten PSRAM.",
|
||
options: [
|
||
{ value: "heavy_psram", label: "Hohe PSRAM-Dichte (>4 MB bis 64 MB für Videopuffer, KI oder LVGL)", icon: "memory_heavy_psram" },
|
||
{ value: "moderate_sram", label: "Ausgewogener interner SRAM (320 KB bis 512 KB) mit oder ohne leichtes PSRAM", icon: "memory_moderate_sram" },
|
||
{ value: "minimal_cost", label: "Kompakter und wirtschaftlicher Speicher (Schlanke, kostengünstige Firmware)", icon: "memory_minimal_cost" },
|
||
]
|
||
},
|
||
{
|
||
id: "ai",
|
||
question: "6. Verwendet Ihr Projekt lokale Künstliche Intelligenz (Edge AI / TinyML)?",
|
||
description: "Hardware-Vektorbefehle und dedizierte neuronale Beschleuniger verkürzen Inferenzzeiten neuronaler Netze von Sekunden auf Millisekunden.",
|
||
options: [
|
||
{ value: "ai_vector", label: "Ja, Hardware-KI-Vektorbeschleunigung erforderlich (TinyML / Vision)", icon: "ai_ai_vector" },
|
||
{ value: "standard", label: "Nein, standardmäßige logische und mathematische Verarbeitung genügt", icon: "ai_standard" },
|
||
]
|
||
},
|
||
{
|
||
id: "security",
|
||
question: "7. Welches Maß an Hardwaresicherheit und Kryptographie erfordert das Produkt?",
|
||
description: "Die Serien unterscheiden sich in der Unterstützung von Key Manager, Schutz vor Seitenkanalangriffen (DPA), elliptischen Kurven (ECC/ECDSA) und AES-Beschleunigern.",
|
||
options: [
|
||
{ value: "key_manager_dpa", label: "Maximaler Schutz: Hardware-Key-Manager (Schlüssel isoliert von CPU) und DPA-Schutz", icon: "security_key_manager_dpa" },
|
||
{ value: "hardware_ecc_ecdsa", label: "Hardware-Beschleuniger für elliptische Kurven (ECC) und ECDSA-Signatur", icon: "security_hardware_ecc_ecdsa" },
|
||
{ value: "secure_boot", label: "Secure Boot V2 und Flash-Verschlüsselung (XTS-AES) gegen Firmware-Kopien", icon: "security_secure_boot" },
|
||
{ value: "standard_tls", label: "Standardmäßige TLS/HTTPS-Kommunikation (Hardware-AES- und SHA-Beschleuniger)", icon: "security_standard_tls" },
|
||
]
|
||
},
|
||
{
|
||
id: "ecosystem",
|
||
question: "8. Welche Entwicklungsumgebung bevorzugen Sie?",
|
||
description: "Ausgereifte Chips bieten breite offizielle Unterstützung im Arduino Core mit Hunderten fertigen Bibliotheken, neuere Chips nutzen ESP-IDF.",
|
||
options: [
|
||
{ value: "arduino_ready", label: "Bereit für Arduino IDE (ausgereifter Support mit großem Bibliotheksangebot)", icon: "ecosystem_arduino_ready" },
|
||
{ value: "advanced_idf", label: "Professionelles ESP-IDF oder offen für Silizium der nächsten Generation (S31, H4 usw.)", icon: "ecosystem_advanced_idf" },
|
||
]
|
||
}
|
||
];
|
||
const QUESTIONS_ZH = [
|
||
{
|
||
id: "category",
|
||
question: "1. 你的项目主要面向什么应用?",
|
||
description: "对应用分类,有助于在外形尺寸、单价、多媒体总线和计算性能之间取得平衡。",
|
||
options: [
|
||
{ value: "smarthome", label: "自动化 / 智能家居 / 联网设备", icon: "category_smarthome" },
|
||
{ value: "multimedia", label: "图形界面(LCD/MIPI 显示屏 / 摄像头 / HMI)", icon: "category_multimedia" },
|
||
{ value: "ai_edge", label: "边缘人工智能(视觉 / 音频 / TinyML)", icon: "category_ai_edge" },
|
||
{ value: "wearable", label: "便携 / 可穿戴设备(电池供电)", icon: "category_wearable" },
|
||
{ value: "industrial", label: "工业 / 机器人 / 现场总线与自动化", icon: "category_industrial" },
|
||
{ value: "basic_iot", label: "基础物联网 / 超低成本联网传感器", icon: "category_basic_iot" },
|
||
]
|
||
},
|
||
{
|
||
id: "connectivity",
|
||
question: "2. 你需要哪种无线或有线网络技术?",
|
||
description: "ESP32 生态覆盖从双频 Wi-Fi 6(2.4/5GHz)、蓝牙 6、802.15.4 Mesh,到有线以太网和经典蓝牙的各种选择。",
|
||
options: [
|
||
{ value: "wifi6_dualband", label: "双频 Wi-Fi 6(2.4 GHz 和 5 GHz)+ 蓝牙 6.0", icon: "connectivity_wifi6_dualband" },
|
||
{ value: "wifi6_mesh", label: "Wi-Fi 6(2.4 GHz)+ Matter / Zigbee 3.0 / Thread(802.15.4)", icon: "connectivity_wifi6_mesh" },
|
||
{ value: "mesh_only", label: "仅 Mesh 射频(Zigbee / Thread / Matter)+ BLE(无 Wi-Fi)", icon: "connectivity_mesh_only" },
|
||
{ value: "wifi_ble", label: "传统 Wi-Fi 4(2.4 GHz)+ 低功耗蓝牙", icon: "connectivity_wifi_ble" },
|
||
{ value: "bt_classic_audio", label: "经典蓝牙 BR/EDR(A2DP 音频 / SPP 串口)", icon: "connectivity_bt_classic_audio" },
|
||
{ value: "ethernet", label: "工业有线网络(集成以太网 MAC)", icon: "connectivity_ethernet" },
|
||
{ value: "none_local", label: "仅本地处理 / 无无线连接", icon: "connectivity_none_local" },
|
||
]
|
||
},
|
||
{
|
||
id: "power",
|
||
question: "3. 设备如何供电?",
|
||
description: "供电方式决定了是否需要超低功耗的深度睡眠模式(<10µA),以及用于持续监测的 ULP 协处理器。",
|
||
options: [
|
||
{ value: "battery_critical", label: "电池 / 太阳能(深度睡眠电流超低,<10µA)", icon: "power_battery_critical" },
|
||
{ value: "ulp_coprocessor", label: "混合供电 / 通过 ULP 协处理器在后台监测传感器", icon: "power_ulp_coprocessor" },
|
||
{ value: "always_on", label: "市电、外部电源或 USB(常开 / 高性能)", icon: "power_always_on" },
|
||
]
|
||
},
|
||
{
|
||
id: "hardware",
|
||
question: "4. 你会用到哪些专用外设或物理总线?",
|
||
description: "某些功能需要专用的硬件模块,例如 MIPI/RGB 视频接口、工业 CAN 总线或原生 USB。",
|
||
options: [
|
||
{ value: "mipi_multimedia", label: "图形 LCD 显示屏(RGB/MIPI DSI)或摄像头(DVP/MIPI CSI)", icon: "hardware_mipi_multimedia" },
|
||
{ value: "usb_otg", label: "原生 USB OTG / 主机(模拟 HID 键盘/鼠标、CDC,或主机模式)", icon: "hardware_usb_otg" },
|
||
{ value: "can_twai", label: "车载 / 工业 CAN 总线(TWAI 或 CAN-FD)", icon: "hardware_can_twai" },
|
||
{ value: "dac_audio", label: "带集成 DAC 的模拟音频(直接输出声音)", icon: "hardware_dac_audio" },
|
||
{ value: "many_gpios", label: "大量扩展引脚(超过 35 个物理 GPIO)", icon: "hardware_many_gpios" },
|
||
{ value: "standard_sensors", label: "使用常见总线的普通传感器(I2C、SPI、UART、PWM)", icon: "hardware_standard_sensors" },
|
||
]
|
||
},
|
||
{
|
||
id: "memory",
|
||
question: "5. 需要多大容量的 RAM / PSRAM?",
|
||
description: "图形界面项目(LVGL)、计算机视觉、音频或较重的协议栈,需要高密度的外部或集成 PSRAM。",
|
||
options: [
|
||
{ value: "heavy_psram", label: "高容量 PSRAM(>4 MB 到 64 MB,用于视频缓冲、AI 或 LVGL)", icon: "memory_heavy_psram" },
|
||
{ value: "moderate_sram", label: "均衡的内部 SRAM(320 KB 到 512 KB),可搭配少量 PSRAM 或不搭配", icon: "memory_moderate_sram" },
|
||
{ value: "minimal_cost", label: "紧凑经济的内存(精简、低成本的固件)", icon: "memory_minimal_cost" },
|
||
]
|
||
},
|
||
{
|
||
id: "ai",
|
||
question: "6. 你的项目会使用本地人工智能(边缘 AI / TinyML)吗?",
|
||
description: "硬件向量指令和专用神经网络加速器,可把神经网络推理时间从秒级缩短到毫秒级。",
|
||
options: [
|
||
{ value: "ai_vector", label: "是,我需要硬件 AI 向量加速(TinyML / 视觉)", icon: "ai_ai_vector" },
|
||
{ value: "standard", label: "否,普通的逻辑和数学运算就足够了", icon: "ai_standard" },
|
||
]
|
||
},
|
||
{
|
||
id: "security",
|
||
question: "7. 产品需要什么级别的硬件安全与加密?",
|
||
description: "各系列在密钥管理器、侧信道攻击防护(DPA)、椭圆曲线(ECC/ECDSA)以及 AES 加速器方面各不相同。",
|
||
options: [
|
||
{ value: "key_manager_dpa", label: "最高级别防护:硬件密钥管理器(与 CPU 隔离)和 DPA 防护", icon: "security_key_manager_dpa" },
|
||
{ value: "hardware_ecc_ecdsa", label: "硬件椭圆曲线加速器(ECC)和 ECDSA 数字签名", icon: "security_hardware_ecc_ecdsa" },
|
||
{ value: "secure_boot", label: "安全启动 V2 和闪存加密(XTS-AES),防止固件被克隆", icon: "security_secure_boot" },
|
||
{ value: "standard_tls", label: "标准的 TLS/HTTPS 通信(硬件 AES 和 SHA 加速器)", icon: "security_standard_tls" },
|
||
]
|
||
},
|
||
{
|
||
id: "ecosystem",
|
||
question: "8. 你偏好什么开发环境?",
|
||
description: "成熟的芯片在 Arduino 核心中有广泛的官方支持和数百个现成的库,而较新的芯片则先从 ESP-IDF 开始。",
|
||
options: [
|
||
{ value: "arduino_ready", label: "可直接用 Arduino IDE(支持成熟,库生态丰富)", icon: "ecosystem_arduino_ready" },
|
||
{ value: "advanced_idf", label: "专业的 ESP-IDF,或愿意尝试新一代芯片(S31、H4 等)", icon: "ecosystem_advanced_idf" },
|
||
]
|
||
}
|
||
];
|
||
|
||
const QUESTIONS_ES = [
|
||
{
|
||
id: "category",
|
||
question: "1. ¿Cuál es el enfoque principal o aplicación de su proyecto?",
|
||
description: "Categorizar su aplicación ayuda a equilibrar formato físico, costo por unidad, buses de medios y potencia de cómputo.",
|
||
options: [
|
||
{ value: "smarthome", label: "Automatización / Hogar inteligente / Dispositivos conectados", icon: "category_smarthome" },
|
||
{ value: "multimedia", label: "Interfaces gráficas (Pantallas LCD/MIPI / Cámaras / HMI)", icon: "category_multimedia" },
|
||
{ value: "ai_edge", label: "Inteligencia artificial en el borde (Visión / Audio / TinyML)", icon: "category_ai_edge" },
|
||
{ value: "wearable", label: "Dispositivo portátil / Vestible (Alimentado por batería)", icon: "category_wearable" },
|
||
{ value: "industrial", label: "Industrial / Robótica / Redes de campo y automatización", icon: "category_industrial" },
|
||
{ value: "basic_iot", label: "IoT básico / Sensor conectado de ultra bajo costo", icon: "category_basic_iot" },
|
||
]
|
||
},
|
||
{
|
||
id: "connectivity",
|
||
question: "2. ¿Qué tecnología de red inalámbrica o cableada necesita?",
|
||
description: "El ecosistema ESP32 ofrece desde radios Wi-Fi 6 de doble banda (2.4/5GHz), Bluetooth 6 y redes Mesh 802.15.4 hasta Ethernet cableado y Bluetooth clásico.",
|
||
options: [
|
||
{ value: "wifi6_dualband", label: "Wi-Fi 6 de doble banda (2.4 GHz y 5 GHz) + Bluetooth 6.0", icon: "connectivity_wifi6_dualband" },
|
||
{ value: "wifi6_mesh", label: "Wi-Fi 6 (2.4 GHz) + Matter / Zigbee 3.0 / Thread (802.15.4)", icon: "connectivity_wifi6_mesh" },
|
||
{ value: "mesh_only", label: "Solo radio Mesh (Zigbee / Thread / Matter) + BLE (sin Wi-Fi)", icon: "connectivity_mesh_only" },
|
||
{ value: "wifi_ble", label: "Wi-Fi 4 tradicional (2.4 GHz) + Bluetooth LE", icon: "connectivity_wifi_ble" },
|
||
{ value: "bt_classic_audio", label: "Bluetooth clásico BR/EDR (Audio A2DP / SPP serie)", icon: "connectivity_bt_classic_audio" },
|
||
{ value: "ethernet", label: "Red cableada industrial (controlador Ethernet MAC integrado)", icon: "connectivity_ethernet" },
|
||
{ value: "none_local", label: "Solo procesamiento local / Sin conexión inalámbrica", icon: "connectivity_none_local" },
|
||
]
|
||
},
|
||
{
|
||
id: "power",
|
||
question: "3. ¿Cómo se alimentará eléctricamente el dispositivo?",
|
||
description: "La elección de la fuente define la importancia de modos Deep Sleep ultra bajos (<10µA) y coprocesadores ULP para monitoreo continuo.",
|
||
options: [
|
||
{ value: "battery_critical", label: "Batería / Solar (Consumo ultra bajo en Deep Sleep <10µA)", icon: "power_battery_critical" },
|
||
{ value: "ulp_coprocessor", label: "Mixto / Monitorear sensores en segundo plano mediante coprocesador ULP", icon: "power_ulp_coprocessor" },
|
||
{ value: "always_on", label: "Enchufe, fuente externa o USB (Siempre activo / Alto rendimiento)", icon: "power_always_on" },
|
||
]
|
||
},
|
||
{
|
||
id: "hardware",
|
||
question: "4. ¿Qué periféricos o buses físicos especiales va a utilizar?",
|
||
description: "Algunas funciones requieren bloques de silicio dedicados, como interfaces de video MIPI/RGB, bus CAN industrial o USB nativo.",
|
||
options: [
|
||
{ value: "mipi_multimedia", label: "Pantalla gráfica LCD (RGB/MIPI DSI) o Cámaras (DVP/MIPI CSI)", icon: "hardware_mipi_multimedia" },
|
||
{ value: "usb_otg", label: "USB nativo OTG / Host (Emular teclado/ratón HID, CDC o modo Host)", icon: "hardware_usb_otg" },
|
||
{ value: "can_twai", label: "Bus automotriz / industrial CAN (TWAI o CAN-FD)", icon: "hardware_can_twai" },
|
||
{ value: "dac_audio", label: "Audio analógico con DAC integrado (salida de sonido directa)", icon: "hardware_dac_audio" },
|
||
{ value: "many_gpios", label: "Muchos pines libres de expansión (Más de 35 GPIOs físicos)", icon: "hardware_many_gpios" },
|
||
{ value: "standard_sensors", label: "Sensores estándar con buses tradicionales (I2C, SPI, UART, PWM)", icon: "hardware_standard_sensors" },
|
||
]
|
||
},
|
||
{
|
||
id: "memory",
|
||
question: "5. ¿Qué volumen de memoria RAM / PSRAM es necesario?",
|
||
description: "Los proyectos gráficos (LVGL), visión por computadora, audio o pilas pesadas requieren soporte para PSRAM externa o integrada de alta densidad.",
|
||
options: [
|
||
{ value: "heavy_psram", label: "Alta densidad de PSRAM (>4 MB a 64 MB para buffers de video, IA o LVGL)", icon: "memory_heavy_psram" },
|
||
{ value: "moderate_sram", label: "SRAM interna equilibrada (320 KB a 512 KB) con o sin PSRAM ligera", icon: "memory_moderate_sram" },
|
||
{ value: "minimal_cost", label: "Memoria compacta y económica (firmware ligero de bajo costo)", icon: "memory_minimal_cost" },
|
||
]
|
||
},
|
||
{
|
||
id: "ai",
|
||
question: "6. ¿Su proyecto utilizará Inteligencia Artificial local (Edge AI / TinyML)?",
|
||
description: "Las instrucciones vectoriales y los aceleradores neuronales dedicados en hardware reducen el tiempo de inferencia de redes neuronales de segundos a milisegundos.",
|
||
options: [
|
||
{ value: "ai_vector", label: "Sí, necesito acelerador vectorial de IA en hardware (TinyML / Visión)", icon: "ai_ai_vector" },
|
||
{ value: "standard", label: "No, el procesamiento lógico y matemático estándar es suficiente", icon: "ai_standard" },
|
||
]
|
||
},
|
||
{
|
||
id: "security",
|
||
question: "7. ¿Qué nivel de seguridad y criptografía por hardware exige el producto?",
|
||
description: "Las series difieren en soporte para Key Manager, protección contra ataques de canal lateral (DPA), curvas elípticas (ECC/ECDSA) y aceleradores AES.",
|
||
options: [
|
||
{ value: "key_manager_dpa", label: "Protección máxima: Key Manager en hardware (clave aislada de la CPU) y Protección DPA", icon: "security_key_manager_dpa" },
|
||
{ value: "hardware_ecc_ecdsa", label: "Acelerador de curvas elípticas (ECC) y firma digital ECDSA por hardware", icon: "security_hardware_ecc_ecdsa" },
|
||
{ value: "secure_boot", label: "Secure Boot V2 y cifrado de flash (XTS-AES) contra copia de firmware", icon: "security_secure_boot" },
|
||
{ value: "standard_tls", label: "Comunicación TLS/HTTPS estándar (Aceleradores AES y SHA por hardware)", icon: "security_standard_tls" },
|
||
]
|
||
},
|
||
{
|
||
id: "ecosystem",
|
||
question: "8. ¿Cuál es su preferencia de entorno de desarrollo?",
|
||
description: "Los chips más maduros tienen amplio soporte oficial en Arduino Core con cientos de bibliotecas disponibles, mientras que chips preliminares utilizan ESP-IDF.",
|
||
options: [
|
||
{ value: "arduino_ready", label: "Listo para Arduino IDE (soporte maduro con amplia colección de bibliotecas)", icon: "ecosystem_arduino_ready" },
|
||
{ value: "advanced_idf", label: "ESP-IDF profesional o abierto a silicio de última generación (S31, H4, etc.)", icon: "ecosystem_advanced_idf" },
|
||
]
|
||
}
|
||
];
|
||
|
||
const FILTROS_PT = [
|
||
{ key: "wifi6", label: "Wi-Fi 6 (802.11ax)" },
|
||
{ key: "wifi5ghz", label: "Wi-Fi dual-band (5 GHz)" },
|
||
{ key: "bluetoothClassic", label: "Bluetooth Clássico (A2DP)" },
|
||
{ key: "leAudio", label: "Bluetooth LE Audio" },
|
||
{ key: "matter", label: "Matter / 802.15.4" },
|
||
{ key: "ethernet", label: "Ethernet MAC" },
|
||
{ key: "aiAccel", label: "Aceleração vetorial de IA" },
|
||
{ key: "psram", label: "Suporte a PSRAM" },
|
||
{ key: "mipiDisplayCamera", label: "Telas e câmeras (MIPI/RGB)" },
|
||
{ key: "usbOTG", label: "USB nativo OTG" },
|
||
{ key: "canBus", label: "Barramento CAN / TWAI" },
|
||
{ key: "dac", label: "Conversor DAC" },
|
||
{ key: "touch", label: "Touch capacitivo" },
|
||
{ key: "arduinoReady", label: "Suporte ao Arduino Core" },
|
||
{ key: "eccHardware", label: "Curvas elípticas (ECC)" },
|
||
{ key: "ecdsaHardware", label: "Assinatura ECDSA em hardware" },
|
||
{ key: "keyManager", label: "Key Manager em hardware" },
|
||
{ key: "secureBootV2", label: "Secure Boot V2" },
|
||
];
|
||
|
||
const FILTROS_EN = [
|
||
{ key: "wifi6", label: "Wi-Fi 6 (802.11ax)" },
|
||
{ key: "wifi5ghz", label: "Dual-band Wi-Fi (5 GHz)" },
|
||
{ key: "bluetoothClassic", label: "Bluetooth Classic (A2DP)" },
|
||
{ key: "leAudio", label: "Bluetooth LE Audio" },
|
||
{ key: "matter", label: "Matter / 802.15.4" },
|
||
{ key: "ethernet", label: "Ethernet MAC" },
|
||
{ key: "aiAccel", label: "AI vector acceleration" },
|
||
{ key: "psram", label: "PSRAM support" },
|
||
{ key: "mipiDisplayCamera", label: "Displays and cameras (MIPI/RGB)" },
|
||
{ key: "usbOTG", label: "Native USB OTG" },
|
||
{ key: "canBus", label: "CAN / TWAI bus" },
|
||
{ key: "dac", label: "DAC converter" },
|
||
{ key: "touch", label: "Capacitive touch" },
|
||
{ key: "arduinoReady", label: "Arduino Core support" },
|
||
{ key: "eccHardware", label: "Elliptic curves (ECC)" },
|
||
{ key: "ecdsaHardware", label: "Hardware ECDSA signature" },
|
||
{ key: "keyManager", label: "Hardware Key Manager" },
|
||
{ key: "secureBootV2", label: "Secure Boot V2" },
|
||
];
|
||
|
||
|
||
const FILTROS_FR = [
|
||
{ key: "wifi6", label: "Wi-Fi 6 (802.11ax)" },
|
||
{ key: "wifi5ghz", label: "Wi-Fi bi-bande (5 GHz)" },
|
||
{ key: "bluetoothClassic", label: "Bluetooth classique (A2DP)" },
|
||
{ key: "leAudio", label: "Bluetooth LE Audio" },
|
||
{ key: "matter", label: "Matter / 802.15.4" },
|
||
{ key: "ethernet", label: "Ethernet MAC" },
|
||
{ key: "aiAccel", label: "Accélération vectorielle IA" },
|
||
{ key: "psram", label: "Prise en charge PSRAM" },
|
||
{ key: "mipiDisplayCamera", label: "Écrans et caméras (MIPI/RGB)" },
|
||
{ key: "usbOTG", label: "USB natif OTG" },
|
||
{ key: "canBus", label: "Bus CAN / TWAI" },
|
||
{ key: "dac", label: "Convertisseur DAC" },
|
||
{ key: "touch", label: "Touch capacitif" },
|
||
{ key: "arduinoReady", label: "Support Arduino Core" },
|
||
{ key: "eccHardware", label: "Courbes elliptiques (ECC)" },
|
||
{ key: "ecdsaHardware", label: "Signature ECDSA matérielle" },
|
||
{ key: "keyManager", label: "Key Manager matériel" },
|
||
{ key: "secureBootV2", label: "Secure Boot V2" },
|
||
];
|
||
|
||
const FILTROS_DE = [
|
||
{ key: "wifi6", label: "Wi-Fi 6 (802.11ax)" },
|
||
{ key: "wifi5ghz", label: "Dual-Band Wi-Fi (5 GHz)" },
|
||
{ key: "bluetoothClassic", label: "Klassisches Bluetooth (A2DP)" },
|
||
{ key: "leAudio", label: "Bluetooth LE Audio" },
|
||
{ key: "matter", label: "Matter / 802.15.4" },
|
||
{ key: "ethernet", label: "Ethernet MAC" },
|
||
{ key: "aiAccel", label: "KI-Vektorbeschleunigung" },
|
||
{ key: "psram", label: "PSRAM-Unterstützung" },
|
||
{ key: "mipiDisplayCamera", label: "Displays und Kameras (MIPI/RGB)" },
|
||
{ key: "usbOTG", label: "Natives USB OTG" },
|
||
{ key: "canBus", label: "CAN / TWAI-Bus" },
|
||
{ key: "dac", label: "DAC-Wandler" },
|
||
{ key: "touch", label: "Kapazitiver Touch" },
|
||
{ key: "arduinoReady", label: "Arduino Core-Unterstützung" },
|
||
{ key: "eccHardware", label: "Elliptische Kurven (ECC)" },
|
||
{ key: "ecdsaHardware", label: "Hardware-ECDSA-Signatur" },
|
||
{ key: "keyManager", label: "Hardware-Key-Manager" },
|
||
{ key: "secureBootV2", label: "Secure Boot V2" },
|
||
];
|
||
const FILTROS_ZH = [
|
||
{ key: "wifi6", label: "Wi-Fi 6(802.11ax)" },
|
||
{ key: "wifi5ghz", label: "双频 Wi-Fi(5 GHz)" },
|
||
{ key: "bluetoothClassic", label: "经典蓝牙(A2DP)" },
|
||
{ key: "leAudio", label: "蓝牙 LE Audio" },
|
||
{ key: "matter", label: "Matter / 802.15.4" },
|
||
{ key: "ethernet", label: "以太网 MAC" },
|
||
{ key: "aiAccel", label: "AI 向量加速" },
|
||
{ key: "psram", label: "支持 PSRAM" },
|
||
{ key: "mipiDisplayCamera", label: "显示屏与摄像头(MIPI/RGB)" },
|
||
{ key: "usbOTG", label: "原生 USB OTG" },
|
||
{ key: "canBus", label: "CAN / TWAI 总线" },
|
||
{ key: "dac", label: "DAC 转换器" },
|
||
{ key: "touch", label: "电容触摸" },
|
||
{ key: "arduinoReady", label: "支持 Arduino 核心" },
|
||
{ key: "eccHardware", label: "椭圆曲线(ECC)" },
|
||
{ key: "ecdsaHardware", label: "硬件 ECDSA 签名" },
|
||
{ key: "keyManager", label: "硬件密钥管理器" },
|
||
{ key: "secureBootV2", label: "安全启动 V2" },
|
||
];
|
||
|
||
const FILTROS_ES = [
|
||
{ key: "wifi6", label: "Wi-Fi 6 (802.11ax)" },
|
||
{ key: "wifi5ghz", label: "Wi-Fi de doble banda (5 GHz)" },
|
||
{ key: "bluetoothClassic", label: "Bluetooth clásico (A2DP)" },
|
||
{ key: "leAudio", label: "Bluetooth LE Audio" },
|
||
{ key: "matter", label: "Matter / 802.15.4" },
|
||
{ key: "ethernet", label: "Ethernet MAC" },
|
||
{ key: "aiAccel", label: "Aceleración vectorial de IA" },
|
||
{ key: "psram", label: "Soporte para PSRAM" },
|
||
{ key: "mipiDisplayCamera", label: "Pantallas y cámaras (MIPI/RGB)" },
|
||
{ key: "usbOTG", label: "USB nativo OTG" },
|
||
{ key: "canBus", label: "Bus CAN / TWAI" },
|
||
{ key: "dac", label: "Conversor DAC" },
|
||
{ key: "touch", label: "Touch capacitivo" },
|
||
{ key: "arduinoReady", label: "Soporte para Arduino Core" },
|
||
{ key: "eccHardware", label: "Curvas elípticas (ECC)" },
|
||
{ key: "ecdsaHardware", label: "Firma ECDSA en hardware" },
|
||
{ key: "keyManager", label: "Key Manager en hardware" },
|
||
{ key: "secureBootV2", label: "Secure Boot V2" },
|
||
];
|
||
|
||
const ROTULOS_ETAPA_PT = {
|
||
category: "Aplicação",
|
||
connectivity: "Conectividade",
|
||
power: "Alimentação",
|
||
hardware: "Periféricos",
|
||
memory: "Memória",
|
||
ai: "Inteligência artificial",
|
||
security: "Segurança",
|
||
ecosystem: "Ambiente de desenvolvimento",
|
||
};
|
||
|
||
const ROTULOS_ETAPA_EN = {
|
||
category: "Application",
|
||
connectivity: "Connectivity",
|
||
power: "Power Supply",
|
||
hardware: "Peripherals",
|
||
memory: "Memory",
|
||
ai: "Artificial Intelligence",
|
||
security: "Security",
|
||
ecosystem: "Development Environment",
|
||
};
|
||
|
||
|
||
const ROTULOS_ETAPA_FR = {
|
||
category: "Application",
|
||
connectivity: "Connectivité",
|
||
power: "Alimentation",
|
||
hardware: "Périphériques",
|
||
memory: "Mémoire",
|
||
ai: "Intelligence artificielle",
|
||
security: "Sécurité",
|
||
ecosystem: "Environnement de développement",
|
||
};
|
||
|
||
const ROTULOS_ETAPA_DE = {
|
||
category: "Anwendung",
|
||
connectivity: "Konnektivität",
|
||
power: "Stromversorgung",
|
||
hardware: "Peripherie",
|
||
memory: "Speicher",
|
||
ai: "Künstliche Intelligenz",
|
||
security: "Sicherheit",
|
||
ecosystem: "Entwicklungsumgebung",
|
||
};
|
||
const ROTULOS_ETAPA_ZH = {
|
||
category: "应用",
|
||
connectivity: "连接",
|
||
power: "供电",
|
||
hardware: "外设",
|
||
memory: "内存",
|
||
ai: "人工智能",
|
||
security: "安全",
|
||
ecosystem: "开发环境",
|
||
};
|
||
|
||
const ROTULOS_ETAPA_ES = {
|
||
category: "Aplicación",
|
||
connectivity: "Conectividad",
|
||
power: "Alimentación",
|
||
hardware: "Periféricos",
|
||
memory: "Memoria",
|
||
ai: "Inteligencia artificial",
|
||
security: "Seguridad",
|
||
ecosystem: "Entorno de desarrollo",
|
||
};
|
||
|
||
export default function Seletor() {
|
||
const pathname = usePathname();
|
||
const isEn = pathname?.startsWith("/en");
|
||
const isEs = pathname?.startsWith("/es");
|
||
const isFr = pathname?.startsWith("/fr");
|
||
const isDe = pathname?.startsWith("/de");
|
||
const isZh = pathname?.startsWith("/zh-CN");
|
||
const currentLocale = isZh ? "zh-CN" : isDe ? "de" : isFr ? "fr" : isEs ? "es" : isEn ? "en" : "pt";
|
||
|
||
const seriesData = isZh ? seriesDataZh : isDe ? seriesDataDe : isFr ? seriesDataFr : isEs ? seriesDataEs : isEn ? seriesDataEn : seriesDataPt;
|
||
const PRESETS = isZh ? PRESETS_ZH : isDe ? PRESETS_DE : isFr ? PRESETS_FR : isEs ? PRESETS_ES : isEn ? PRESETS_EN : PRESETS_PT;
|
||
const questions = isZh ? QUESTIONS_ZH : isDe ? QUESTIONS_DE : isFr ? QUESTIONS_FR : isEs ? QUESTIONS_ES : isEn ? QUESTIONS_EN : QUESTIONS_PT;
|
||
const FILTROS = isZh ? FILTROS_ZH : isDe ? FILTROS_DE : isFr ? FILTROS_FR : isEs ? FILTROS_ES : isEn ? FILTROS_EN : FILTROS_PT;
|
||
const ROTULOS_ETAPA = isZh ? ROTULOS_ETAPA_ZH : isDe ? ROTULOS_ETAPA_DE : isFr ? ROTULOS_ETAPA_FR : isEs ? ROTULOS_ETAPA_ES : isEn ? ROTULOS_ETAPA_EN : ROTULOS_ETAPA_PT;
|
||
|
||
const [mode, setMode] = useState("wizard"); // "wizard" | "filter"
|
||
const [currentStep, setCurrentStep] = useState(0);
|
||
const [currentAnswer, setCurrentAnswer] = useState(null);
|
||
const [activePreset, setActivePreset] = useState(null);
|
||
|
||
const [answers, setAnswers] = useState({
|
||
category: null,
|
||
connectivity: null,
|
||
power: null,
|
||
hardware: null,
|
||
memory: null,
|
||
ai: null,
|
||
security: null,
|
||
ecosystem: null,
|
||
});
|
||
|
||
const [showResults, setShowResults] = useState(false);
|
||
const [showSummary, setShowSummary] = useState(false);
|
||
|
||
// Direct Parametric Filter State (for "filter" mode)
|
||
const [filters, setFilters] = useState({
|
||
wifi6: false,
|
||
wifi5ghz: false,
|
||
bluetoothClassic: false,
|
||
leAudio: false,
|
||
matter: false,
|
||
ethernet: false,
|
||
aiAccel: false,
|
||
psram: false,
|
||
mipiDisplayCamera: false,
|
||
usbOTG: false,
|
||
canBus: false,
|
||
dac: false,
|
||
touch: false,
|
||
arduinoReady: false,
|
||
keyManager: false,
|
||
eccHardware: false,
|
||
ecdsaHardware: false,
|
||
secureBootV2: false,
|
||
});
|
||
|
||
const handleAnswer = (questionId, value) => {
|
||
setCurrentAnswer(value);
|
||
setAnswers(prev => ({ ...prev, [questionId]: value }));
|
||
setActivePreset(null);
|
||
};
|
||
|
||
const handleNext = () => {
|
||
if (currentAnswer !== null) {
|
||
if (currentStep < questions.length - 1) {
|
||
const nextStep = currentStep + 1;
|
||
setCurrentStep(nextStep);
|
||
setCurrentAnswer(answers[questions[nextStep].id] || null);
|
||
} else {
|
||
setShowSummary(true);
|
||
}
|
||
}
|
||
};
|
||
|
||
const goBack = () => {
|
||
if (currentStep > 0) {
|
||
const prevStep = currentStep - 1;
|
||
setCurrentStep(prevStep);
|
||
setCurrentAnswer(answers[questions[prevStep].id] || null);
|
||
}
|
||
};
|
||
|
||
const resetQuiz = () => {
|
||
setCurrentStep(0);
|
||
setCurrentAnswer(null);
|
||
setShowResults(false);
|
||
setShowSummary(false);
|
||
setActivePreset(null);
|
||
setAnswers({
|
||
category: null,
|
||
connectivity: null,
|
||
power: null,
|
||
hardware: null,
|
||
memory: null,
|
||
ai: null,
|
||
security: null,
|
||
ecosystem: null,
|
||
});
|
||
};
|
||
|
||
const applyPreset = (preset) => {
|
||
setAnswers(preset.answers);
|
||
setActivePreset(preset.id);
|
||
setCurrentStep(questions.length - 1);
|
||
setCurrentAnswer(preset.answers.ecosystem);
|
||
setShowSummary(false);
|
||
setShowResults(true);
|
||
};
|
||
|
||
// Comprehensive Multi-Criteria Scoring Engine based on series data
|
||
const calculateRecommendations = () => {
|
||
const scores = {};
|
||
const reasons = {};
|
||
const alerts = {};
|
||
const r = (pt, en, es, fr, de, zh) => isZh ? zh : isDe ? de : isFr ? fr : isEs ? es : isEn ? en : pt;
|
||
|
||
Object.keys(seriesData).forEach(key => {
|
||
scores[key] = 0;
|
||
reasons[key] = [];
|
||
alerts[key] = [];
|
||
const serie = seriesData[key];
|
||
const seg = serie.seguranca || {};
|
||
|
||
const hasMatter = ehSim(serie.matter);
|
||
const hasNoWifi = ehNao(serie.wifi);
|
||
const hasNoBluetooth = ehNao(serie.bluetooth);
|
||
|
||
// 1. CATEGORIA (category)
|
||
if (answers.category === "smarthome") {
|
||
if (hasMatter) {
|
||
scores[key] += 25;
|
||
reasons[key].push(r("Suporte nativo a Matter para interoperabilidade residencial inteligente", "Native Matter support for smart home interoperability", "Soporte nativo para Matter para interoperabilidad en el hogar inteligente", "Prise en charge native de Matter pour l'interopérabilité domotique intelligente", "Native Matter-Unterstützung für Smart-Home-Interoperabilität", "原生支持 Matter,可实现智能家居互操作"));
|
||
}
|
||
if (!ehNao(serie.zigbee_thread)) {
|
||
scores[key] += 20;
|
||
reasons[key].push(r("Rádio 802.15.4 integrado compatível com Zigbee 3.0 e Thread", "Integrated 802.15.4 radio compatible with Zigbee 3.0 and Thread", "Radio 802.15.4 integrada compatible con Zigbee 3.0 y Thread", "Radio 802.15.4 intégrée compatible avec Zigbee 3.0 et Thread", "Integriertes 802.15.4-Funkmodul kompatibel mit Zigbee 3.0 und Thread", "集成 802.15.4 射频,兼容 Zigbee 3.0 和 Thread"));
|
||
}
|
||
if (!hasNoWifi) {
|
||
scores[key] += 10;
|
||
reasons[key].push(r("Rádio Wi-Fi integrado para conexão direta ao roteador", "Integrated Wi-Fi radio for direct router connection", "Radio Wi-Fi integrada para conexión directa al enrutador", "Radio Wi-Fi intégrée pour connexion directe au routeur", "Integriertes Wi-Fi-Funkmodul für direkte Routerverbindung", "集成 Wi-Fi 射频,可直接连接路由器"));
|
||
}
|
||
} else if (answers.category === "multimedia") {
|
||
if (serie.mipi_dsi || serie.mipi_csi) {
|
||
scores[key] += 35;
|
||
reasons[key].push(r("Barramentos avançados de alta velocidade MIPI DSI (telas) e MIPI CSI (câmeras)", "High-speed MIPI DSI (displays) and MIPI CSI (cameras) buses", "Buses avanzados de alta velocidad MIPI DSI (pantallas) y MIPI CSI (cámaras)", "Bus haute vitesse avancés MIPI DSI (écrans) et MIPI CSI (caméras)", "Erweiterte Hochgeschwindigkeitsbusse MIPI DSI (Displays) und MIPI CSI (Kameras)", "高速 MIPI DSI(显示屏)与 MIPI CSI(摄像头)总线"));
|
||
} else if (serie.lcd || serie.camera) {
|
||
scores[key] += 25;
|
||
reasons[key].push(r("Interfaces dedicadas em hardware para telas LCD RGB e câmeras DVP", "Dedicated hardware interfaces for RGB LCD displays and DVP cameras", "Interfaces de hardware dedicadas para pantallas LCD RGB y cámaras DVP", "Interfaces matérielles dédiées pour écrans LCD RGB et caméras DVP", "Dedizierte Hardwareschnittstellen für RGB-LCD-Displays und DVP-Kameras", "为 RGB LCD 显示屏和 DVP 摄像头提供专用硬件接口"));
|
||
} else {
|
||
scores[key] -= 40;
|
||
alerts[key].push(r("Sem barramentos dedicados para telas coloridas ou câmeras (apenas SPI/I2C simples)", "No dedicated buses for color displays or cameras (SPI/I2C only)", "Sin buses dedicados para pantallas a color o cámaras (solo SPI/I2C)", "Aucun bus dédié pour écrans couleur ou caméras (SPI/I2C simple uniquement)", "Keine dedizierten Busse für Farbdisplays oder Kameras (nur einfaches SPI/I2C)", "没有用于彩色显示屏或摄像头的专用总线(仅有 SPI/I2C)"));
|
||
}
|
||
|
||
if (!ehNao(serie.psram_externa)) {
|
||
scores[key] += 20;
|
||
reasons[key].push(r("Suporte a PSRAM de alta capacidade para framebuffers gráficos e processamento de imagem", "High-capacity PSRAM support for graphics framebuffers and image processing", "Soporte para PSRAM de alta capacidad para búferes de gráficos y procesamiento de imágenes", "Prise en charge de PSRAM haute capacité pour tampons graphiques et traitement d'image", "Unterstützung für hochkapazitiven PSRAM für Grafik-Framebuffer und Bildverarbeitung", "支持大容量 PSRAM,适合图形帧缓冲和图像处理"));
|
||
}
|
||
} else if (answers.category === "ai_edge") {
|
||
if (serie.aceleradores_ia) {
|
||
scores[key] += 40;
|
||
reasons[key].push(r(`Aceleração neural e instruções vetoriais dedicadas (${serie.aceleradores_ia})`, `Dedicated neural acceleration and vector instructions (${serie.aceleradores_ia})`, `Aceleración neuronal e instrucciones vectoriales dedicadas (${serie.aceleradores_ia})`, `Accélération neuronale et instructions vectorielles dédiées (${serie.aceleradores_ia})`, `Neuronale Beschleunigung und dedizierte Vektorbefehle (${serie.aceleradores_ia})`, `专用神经网络加速和向量指令(${serie.aceleradores_ia})`));
|
||
} else {
|
||
scores[key] -= 50;
|
||
alerts[key].push(r("Sem aceleradores neurais dedicados em hardware", "No dedicated hardware neural accelerators", "Sin aceleradores neuronales dedicados en hardware", "Aucun accélérateur neuronal matériel dédié", "Keine dedizierten neuronalen Hardwarebeschleuniger", "没有专用的硬件神经网络加速器"));
|
||
}
|
||
if (serie.nucleos && serie.nucleos.includes("2")) {
|
||
scores[key] += 10;
|
||
reasons[key].push(r("Processador Dual-Core para pipeline paralelo de captura e inferência", "Dual-core processor for parallel capture and inference pipeline", "Procesador dual-core para pipeline paralelo de captura e inferencia", "Processeur Dual-Core pour pipeline parallèle de capture et d'inférence", "Dual-Core-Prozessor für parallele Erfassungs- und Inferenz-Pipelines", "双核处理器,可并行完成采集与推理流水线"));
|
||
}
|
||
} else if (answers.category === "wearable") {
|
||
const sleep = serie.consumo_energia?.deep_sleep;
|
||
if (sleep) {
|
||
const uaMatch = sleep.match(/(\d+)\s*µA/);
|
||
if (uaMatch && parseInt(uaMatch[1]) <= 10) {
|
||
scores[key] += 25;
|
||
reasons[key].push(r(`Consumo em Deep Sleep ultrabaixo de apenas ${sleep} preserva baterias compactas`, `Ultra-low Deep Sleep current of just ${sleep} preserves compact batteries`, `Consumo en Deep Sleep ultrabajo de solo ${sleep} preserva baterías compactas`, `Consommation en Deep Sleep ultra-basse de seulement ${sleep} préservant les batteries compactes`, `Extrem niedriger Deep-Sleep-Strom von nur ${sleep} schont kompakte Batterien`, `深度睡眠电流低至 ${sleep},可让小型电池用得更久`));
|
||
}
|
||
}
|
||
if (!hasNoBluetooth) {
|
||
scores[key] += 15;
|
||
reasons[key].push(r("Rádio Bluetooth de alta eficiência energética para pareamento contínuo", "Energy-efficient Bluetooth radio for continuous pairing", "Radio Bluetooth de alta eficiencia energética para emparejamiento continuo", "Radio Bluetooth à haute efficacité énergétique pour appairage continu", "Energieeffizientes Bluetooth-Funkmodul für kontinuierliches Pairing", "节能的蓝牙射频,适合持续配对"));
|
||
}
|
||
if (key === "ESP32-C2" || key === "ESP32-C3" || key === "ESP32-H2") {
|
||
scores[key] += 10;
|
||
reasons[key].push(r("Encapsulamento compacto QFN reduz o footprint na placa", "Compact QFN package reduces board footprint", "Encapsulado compacto QFN reduce el espacio en la placa", "Boîtier QFN compact réduisant l'empreinte sur la carte", "Kompaktes QFN-Gehäuse reduziert den Platzbedarf auf der Platine", "紧凑的 QFN 封装,减小电路板占用面积"));
|
||
}
|
||
} else if (answers.category === "industrial") {
|
||
if (serie.ethernet || serie.ethernet_mac) {
|
||
scores[key] += 30;
|
||
reasons[key].push(r("Controlador MAC Ethernet integrado para conexões cabeadas industriais imunes a ruídos de RF", "Integrated Ethernet MAC controller for industrial wired connections immune to RF noise", "Controlador Ethernet MAC integrado para conexiones cableadas industriales inmunes al ruido de RF", "Contrôleur MAC Ethernet intégré pour connexions filaires industrielles insensibles aux bruits RF", "Integrierter Ethernet-MAC-Controller für industrielle Kabelverbindungen immun gegen HF-Rauschen", "集成以太网 MAC 控制器,适合不受射频噪声影响的工业有线连接"));
|
||
}
|
||
if (serie.can) {
|
||
scores[key] += 25;
|
||
reasons[key].push(r(`Interface de barramento industrial ${serie.can}`, `Industrial bus interface ${serie.can}`, `Interfaz de bus industrial ${serie.can}`, `Interface de bus industriel ${serie.can}`, `Industrielle Busschnittstelle ${serie.can}`, `工业总线接口 ${serie.can}`));
|
||
}
|
||
if (parseInt(serie.gpio) >= 30) {
|
||
scores[key] += 10;
|
||
reasons[key].push(r(`Ampla contagem de portas digitais (${serie.gpio} GPIOs) para relés e atuadores`, `Large count of digital ports (${serie.gpio} GPIOs) for relays and actuators`, `Gran cantidad de puertos digitales (${serie.gpio} GPIOs) para relés y actuadores`, `Grand nombre de broches numériques (${serie.gpio} GPIO) pour relais et actionneurs`, `Große Anzahl digitaler Anschlüsse (${serie.gpio} GPIOs) für Relais und Aktoren`, `大量数字端口(${serie.gpio} 个 GPIO),可驱动继电器和执行器`));
|
||
}
|
||
} else if (answers.category === "basic_iot") {
|
||
if (key === "ESP32-C2" || key === "ESP32-C3" || key === "ESP32-C61") {
|
||
scores[key] += 30;
|
||
reasons[key].push(r("Excelente relação custo-benefício para sensores e atuadores conectados em escala", "Cost-effective for connected sensors and actuators at scale", "Excelente relación costo-beneficio para sensores y actuadores conectados a escala", "Excellent rapport qualité-prix pour capteurs et actionneurs connectés à grande échelle", "Hervorragendes Preis-Leistungs-Verhältnis für vernetzte Sensoren und Aktoren im Maßstab", "成本低,适合大规模部署的联网传感器和执行器"));
|
||
}
|
||
if (!hasNoWifi && !hasNoBluetooth) {
|
||
scores[key] += 15;
|
||
reasons[key].push(r("Wi-Fi + BLE integrados em módulo econômico", "Integrated Wi-Fi + BLE in an economical module", "Wi-Fi + BLE integrados en un módulo económico", "Wi-Fi + BLE intégrés dans un module économique", "Integriertes Wi-Fi + BLE in einem wirtschaftlichen Modul", "在经济型模组中集成 Wi-Fi + BLE"));
|
||
}
|
||
}
|
||
|
||
// 2. CONECTIVIDADE (connectivity)
|
||
if (answers.connectivity === "wifi6_dualband") {
|
||
if (String(serie.wifi).includes("5 GHz") || /dual-band|双频/i.test(String(serie.wifi))) {
|
||
scores[key] += 50;
|
||
reasons[key].push(r("Exclusivo Wi-Fi 6 Dual-Band (2.4 GHz e 5 GHz) para ambientes com alto ruído de RF", "Exclusive Dual-Band Wi-Fi 6 (2.4 GHz and 5 GHz) for high-noise RF environments", "Exclusivo Wi-Fi 6 de doble banda (2.4 GHz y 5 GHz) para entornos con alto ruido de RF", "Wi-Fi 6 bi-bande exclusif (2,4 GHz et 5 GHz) pour environnements à fort bruit RF", "Exklusives Dual-Band Wi-Fi 6 (2,4 GHz und 5 GHz) für Umgebungen mit hohem HF-Rauschen", "独有的双频 Wi-Fi 6(2.4 GHz 和 5 GHz),适合射频噪声大的环境"));
|
||
} else {
|
||
scores[key] -= 250;
|
||
alerts[key].push(r("Incompatível: Não possui rádio Wi-Fi na faixa de 5 GHz", "Incompatible: No 5 GHz Wi-Fi radio", "Incompatible: No cuenta con radio Wi-Fi en la banda de 5 GHz", "Incompatible : Ne dispose pas de radio Wi-Fi dans la bande 5 GHz", "Inkompatibel: Verfügt über kein Wi-Fi-Funkmodul im 5-GHz-Band", "不兼容:没有 5 GHz Wi-Fi 射频"));
|
||
}
|
||
} else if (answers.connectivity === "wifi6_mesh") {
|
||
if (String(serie.wifi).includes("Wi-Fi 6") && hasMatter) {
|
||
scores[key] += 40;
|
||
reasons[key].push(r("Wi-Fi 6 (802.11ax) somado a rádio 802.15.4 para Thread/Zigbee/Matter", "Wi-Fi 6 (802.11ax) plus 802.15.4 radio for Thread/Zigbee/Matter", "Wi-Fi 6 (802.11ax) sumado a radio 802.15.4 para Thread/Zigbee/Matter", "Wi-Fi 6 (802.11ax) combiné à une radio 802.15.4 pour Thread/Zigbee/Matter", "Wi-Fi 6 (802.11ax) kombiniert mit 802.15.4-Funk für Thread/Zigbee/Matter", "Wi-Fi 6(802.11ax)加上用于 Thread/Zigbee/Matter 的 802.15.4 射频"));
|
||
} else if (hasMatter) {
|
||
scores[key] += 15;
|
||
reasons[key].push(r("Suporte a Matter/Thread, porém sem Wi-Fi 6", "Matter/Thread support, but without Wi-Fi 6", "Soporte para Matter/Thread, pero sin Wi-Fi 6", "Prise en charge de Matter/Thread, mais sans Wi-Fi 6", "Unterstützung für Matter/Thread, jedoch ohne Wi-Fi 6", "支持 Matter/Thread,但没有 Wi-Fi 6"));
|
||
} else {
|
||
scores[key] -= 150;
|
||
alerts[key].push(r("Incompatível: Sem rádio 802.15.4 integrado para Thread/Zigbee", "Incompatible: No integrated 802.15.4 radio for Thread/Zigbee", "Incompatible: Sin radio 802.15.4 integrada para Thread/Zigbee", "Incompatible : Aucune radio 802.15.4 intégrée pour Thread/Zigbee", "Inkompatibel: Kein integriertes 802.15.4-Funkmodul für Thread/Zigbee", "不兼容:没有用于 Thread/Zigbee 的集成 802.15.4 射频"));
|
||
}
|
||
} else if (answers.connectivity === "mesh_only") {
|
||
if (hasNoWifi && hasMatter) {
|
||
scores[key] += 45;
|
||
reasons[key].push(r("Foco 100% em 802.15.4 (Zigbee/Thread/Matter) com baixo consumo e sem rádio Wi-Fi", "100% focus on 802.15.4 (Zigbee/Thread/Matter) with low power and no Wi-Fi radio", "Enfoque 100% en 802.15.4 (Zigbee/Thread/Matter) con bajo consumo y sin radio Wi-Fi", "Focalisé à 100 % sur le 802.15.4 (Zigbee/Thread/Matter) à faible consommation et sans radio Wi-Fi", "100 % Fokus auf 802.15.4 (Zigbee/Thread/Matter) mit geringem Verbrauch und ohne Wi-Fi-Funk", "完全专注于 802.15.4(Zigbee/Thread/Matter),低功耗且没有 Wi-Fi 射频"));
|
||
} else if (hasMatter) {
|
||
scores[key] += 20;
|
||
reasons[key].push(r("Suporta redes Mesh (Zigbee/Thread), mas inclui rádio Wi-Fi adicional", "Supports Mesh networks (Zigbee/Thread), but includes additional Wi-Fi radio", "Soporta redes Mesh (Zigbee/Thread), pero incluye radio Wi-Fi adicional", "Prend en charge les réseaux Mesh (Zigbee/Thread), mais inclut une radio Wi-Fi supplémentaire", "Unterstützt Mesh-Netzwerke (Zigbee/Thread), enthält jedoch ein zusätzliches Wi-Fi-Funkmodul", "支持 Mesh 网络(Zigbee/Thread),但额外带有 Wi-Fi 射频"));
|
||
} else {
|
||
scores[key] -= 180;
|
||
alerts[key].push(r("Incompatível: Sem rádio 802.15.4 para protocolo Thread ou Zigbee", "Incompatible: No 802.15.4 radio for Thread or Zigbee", "Incompatible: Sin radio 802.15.4 para protocolo Thread o Zigbee", "Incompatible : Aucune radio 802.15.4 pour protocole Thread ou Zigbee", "Inkompatibel: Kein 802.15.4-Funkmodul für Thread- oder Zigbee-Protokolle", "不兼容:没有用于 Thread 或 Zigbee 的 802.15.4 射频"));
|
||
}
|
||
} else if (answers.connectivity === "wifi_ble") {
|
||
if (!hasNoWifi && !hasNoBluetooth) {
|
||
scores[key] += 30;
|
||
reasons[key].push(r(`Pilha completa com Wi-Fi (${serie.wifi}) e Bluetooth (${serie.bluetooth})`, `Full stack with Wi-Fi (${serie.wifi}) and Bluetooth (${serie.bluetooth})`, `Pila completa con Wi-Fi (${serie.wifi}) y Bluetooth (${serie.bluetooth})`, `Pile complète avec Wi-Fi (${serie.wifi}) et Bluetooth (${serie.bluetooth})`, `Vollständiger Stack mit Wi-Fi (${serie.wifi}) und Bluetooth (${serie.bluetooth})`, `完整的协议栈:Wi-Fi(${serie.wifi})和蓝牙(${serie.bluetooth})`));
|
||
} else if (!hasNoWifi) {
|
||
scores[key] += 10;
|
||
alerts[key].push(r("Possui Wi-Fi, mas não possui rádio Bluetooth integrado", "Has Wi-Fi, but lacks integrated Bluetooth", "Cuenta con Wi-Fi, pero carece de Bluetooth integrado", "Dispose du Wi-Fi, mais ne possède pas de radio Bluetooth intégrée", "Verfügt über Wi-Fi, jedoch ohne integriertes Bluetooth-Funkmodul", "有 Wi-Fi,但没有集成蓝牙"));
|
||
} else {
|
||
scores[key] -= 200;
|
||
alerts[key].push(r("Incompatível: Não possui rádio Wi-Fi integrado", "Incompatible: No integrated Wi-Fi radio", "Incompatible: No cuenta con radio Wi-Fi integrada", "Incompatible : Ne dispose pas de radio Wi-Fi intégrée", "Inkompatibel: Verfügt über kein integriertes Wi-Fi-Funkmodul", "不兼容:没有集成 Wi-Fi 射频"));
|
||
}
|
||
} else if (answers.connectivity === "bt_classic_audio") {
|
||
if (/Classic|Clássico|Clásico|Classique|Klassisch|经典/.test(String(serie.bluetooth))) {
|
||
scores[key] += 50;
|
||
reasons[key].push(r("Suporte a Bluetooth Clássico (BR/EDR) com perfis A2DP de áudio e SPP serial", "Bluetooth Classic (BR/EDR) support with A2DP audio and serial SPP profiles", "Soporte para Bluetooth clásico (BR/EDR) con perfiles de audio A2DP y SPP serie", "Prise en charge du Bluetooth classique (BR/EDR) avec profils audio A2DP et série SPP", "Unterstützung für klassisches Bluetooth (BR/EDR) mit A2DP-Audioprofilen und seriellem SPP", "支持经典蓝牙(BR/EDR),含 A2DP 音频和串口 SPP 配置文件"));
|
||
} else {
|
||
scores[key] -= 250;
|
||
alerts[key].push(r("Incompatível: Não possui Bluetooth Clássico (apenas BLE, incompatível com áudio A2DP legado)", "Incompatible: No Bluetooth Classic (BLE only, incompatible with legacy A2DP audio)", "Incompatible: No cuenta con Bluetooth clásico (solo BLE, incompatible con audio A2DP heredado)", "Incompatible : Ne dispose pas du Bluetooth classique (BLE uniquement, incompatible avec l'audio A2DP hérité)", "Inkompatibel: Kein klassisches Bluetooth (nur BLE, inkompatibel mit älterem A2DP-Audio)", "不兼容:没有经典蓝牙(仅 BLE,不兼容传统 A2DP 音频)"));
|
||
}
|
||
} else if (answers.connectivity === "ethernet") {
|
||
if (serie.ethernet || serie.ethernet_mac) {
|
||
scores[key] += 45;
|
||
reasons[key].push(r("Controlador MAC Ethernet nativo integrado (requer apenas transceiver PHY)", "Native integrated Ethernet MAC controller (requires only PHY transceiver)", "Controlador Ethernet MAC nativo integrado (requiere solo transceptor PHY)", "Contrôleur MAC Ethernet natif intégré (nécessite uniquement un émetteur-récepteur PHY)", "Nativer integrierter Ethernet-MAC-Controller (benötigt nur PHY-Transceiver)", "原生集成以太网 MAC 控制器(只需外接 PHY 收发器)"));
|
||
} else {
|
||
scores[key] -= 180;
|
||
alerts[key].push(r("Sem MAC Ethernet interno (necessita de módulo SPI Ethernet externo como W5500)", "No internal Ethernet MAC (requires external SPI Ethernet module like W5500)", "Sin Ethernet MAC interno (requiere módulo SPI Ethernet externo como W5500)", "Aucun MAC Ethernet interne (nécessite un module SPI Ethernet externe comme le W5500)", "Kein internes Ethernet-MAC (erfordert externes SPI-Ethernet-Modul wie W5500)", "没有内部以太网 MAC(需要 W5500 这类外部 SPI 以太网模块)"));
|
||
}
|
||
} else if (answers.connectivity === "none_local") {
|
||
if (hasNoWifi || hasNoBluetooth || key === "ESP32-P4") {
|
||
scores[key] += 35;
|
||
reasons[key].push(r("Arquitetura orientada a processamento local dedicado sem custo de transceivers de rádio", "Architecture geared towards dedicated local processing without radio transceiver cost", "Arquitectura orientada a procesamiento local dedicado sin costo de transceptores de radio", "Architecture orientée vers le traitement local dédié sans surcoût d'émetteurs-récepteurs radio", "Architektur für dedizierte lokale Verarbeitung ohne Mehrkosten für Funktransceiver", "架构面向专用的本地处理,省去射频收发器的成本"));
|
||
} else {
|
||
scores[key] += 10;
|
||
}
|
||
}
|
||
|
||
// 3. ALIMENTAÇÃO (power)
|
||
if (answers.power === "battery_critical") {
|
||
const sleep = serie.consumo_energia?.deep_sleep;
|
||
if (sleep) {
|
||
const uaMatch = sleep.match(/(\d+)\s*µA/);
|
||
if (uaMatch && parseInt(uaMatch[1]) <= 10) {
|
||
scores[key] += 25;
|
||
reasons[key].push(r(`Consumo de suspensão de ${sleep} permite operação prolongada por bateria`, `Sleep current of ${sleep} enables extended battery operation`, `Corriente de reposo de ${sleep} permite operación prolongada con batería`, `Consommation de veille de ${sleep} permettant une autonomie prolongée sur batterie`, `Ruhestrom von ${sleep} ermöglicht längeren Batteriebetrieb`, `休眠电流 ${sleep},可支持长时间电池运行`));
|
||
} else {
|
||
scores[key] += 10;
|
||
reasons[key].push(r(`Modo de baixo consumo de ${sleep}`, `Low power mode of ${sleep}`, `Modo de bajo consumo de ${sleep}`, `Mode basse consommation de ${sleep}`, `Energiesparmodus von ${sleep}`, `低功耗模式电流 ${sleep}`));
|
||
}
|
||
}
|
||
if (!ehNao(serie.coprocessador_ulp)) {
|
||
scores[key] += 10;
|
||
reasons[key].push(r("Coprocessador ULP permite checar pinos sem despertar a CPU principal", "ULP coprocessor monitors pins without waking the main CPU", "Coprocesador ULP monitorea pines sin despertar la CPU principal", "Le coprocesseur ULP permet de surveiller les broches sans réveiller le processeur principal", "ULP-Coprozessor ermöglicht die Überwachung von Pins ohne Aufwecken der Haupt-CPU", "ULP 协处理器可在不唤醒主 CPU 的情况下监测引脚"));
|
||
}
|
||
} else if (answers.power === "ulp_coprocessor") {
|
||
if (!ehNao(serie.coprocessador_ulp)) {
|
||
scores[key] += 35;
|
||
reasons[key].push(r(`Coprocessador ULP / CPU de Baixo Consumo (${serie.coprocessador_ulp})`, `ULP coprocessor / Low-power core (${serie.coprocessador_ulp})`, `Coprocesador ULP / Núcleo de bajo consumo (${serie.coprocessador_ulp})`, `Coprocesseur ULP / Cœur basse consommation (${serie.coprocessador_ulp})`, `ULP-Coprozessor / Low-Power-Kern (${serie.coprocessador_ulp})`, `ULP 协处理器 / 低功耗内核(${serie.coprocessador_ulp})`));
|
||
} else {
|
||
scores[key] -= 30;
|
||
alerts[key].push(r("Sem coprocessador ULP dedicado", "No dedicated ULP coprocessor", "Sin coprocesador ULP dedicado", "Aucun coprocesseur ULP dédié", "Kein dedizierter ULP-Coprozessor vorhanden", "没有专用的 ULP 协处理器"));
|
||
}
|
||
} else if (answers.power === "always_on") {
|
||
if (serie.nucleos && serie.nucleos.includes("2")) {
|
||
scores[key] += 15;
|
||
reasons[key].push(r("Processador Dual-Core para multitarefa paralela contínua", "Dual-Core processor for continuous parallel multitasking", "Procesador dual-core para multitarea paralela continua", "Processeur Dual-Core pour multitâche parallèle continu", "Dual-Core-Prozessor für kontinuierliches paralleles Multitasking", "双核处理器,适合持续并行的多任务"));
|
||
}
|
||
const freqMatch = serie.frequencia?.match(/(\d+)\s*MHz/);
|
||
if (freqMatch && parseInt(freqMatch[1]) >= 240) {
|
||
scores[key] += 15;
|
||
reasons[key].push(r(`Frequência de clock de alto desempenho (${serie.frequencia})`, `High-performance clock frequency (${serie.frequencia})`, `Frecuencia de reloj de alto rendimiento (${serie.frequencia})`, `Fréquence d'horloge haute performance (${serie.frequencia})`, `Hochleistungs-Taktfrequenz (${serie.frequencia})`, `高性能主频(${serie.frequencia})`));
|
||
}
|
||
}
|
||
|
||
// 4. HARDWARE & PERIFÉRICOS (hardware)
|
||
if (answers.hardware === "mipi_multimedia") {
|
||
if (serie.mipi_dsi || serie.mipi_csi) {
|
||
scores[key] += 40;
|
||
reasons[key].push(r("Interface MIPI DSI (telas) e MIPI CSI (câmeras) de altíssima taxa de transferência", "High-throughput MIPI DSI (displays) and MIPI CSI (cameras) interface", "Interfaz de muy alta velocidad MIPI DSI (pantallas) y MIPI CSI (cámaras)", "Interface MIPI DSI (écrans) et MIPI CSI (caméras) à très haut débit", "Hochdurchsatz-Schnittstelle MIPI DSI (Displays) und MIPI CSI (Kameras)", "高吞吐的 MIPI DSI(显示屏)和 MIPI CSI(摄像头)接口"));
|
||
} else if (serie.lcd || serie.camera) {
|
||
scores[key] += 25;
|
||
reasons[key].push(r("Interfaces paralelas para LCD RGB e câmeras DVP de 8/16 bits", "Parallel interfaces for RGB LCD and 8/16-bit DVP cameras", "Interfaces paralelas para LCD RGB y cámaras DVP de 8/16 bits", "Interfaces parallèles pour écrans LCD RGB et caméras DVP 8/16 bits", "Parallele Schnittstellen für RGB-LCD und 8/16-Bit-DVP-Kameras", "面向 RGB LCD 和 8/16 位 DVP 摄像头的并行接口"));
|
||
} else {
|
||
scores[key] -= 180;
|
||
alerts[key].push(r("Incompatível: Sem interfaces dedicadas de tela/câmera (limitado a barramento SPI/I2C)", "Incompatible: No dedicated display/camera interfaces (limited to SPI/I2C bus)", "Incompatible: Sin interfaces dedicadas de pantalla/cámara (limitado a bus SPI/I2C)", "Incompatible : Aucune interface dédiée écran/caméra (limité au bus SPI/I2C)", "Inkompatibel: Keine dedizierten Display-/Kameraschnittstellen (auf SPI/I2C beschränkt)", "不兼容:没有专用的显示屏/摄像头接口(仅限 SPI/I2C 总线)"));
|
||
}
|
||
} else if (answers.hardware === "usb_otg") {
|
||
if (serie.usb && /High-Speed OTG|高速 OTG|OTG 2\.0/.test(String(serie.usb))) {
|
||
scores[key] += 40;
|
||
reasons[key].push(r(`Porta USB 2.0 High-Speed OTG (${serie.usb}) para emulação HID, CDC e modo Host`, `USB 2.0 High-Speed OTG port (${serie.usb}) for HID emulation, CDC and Host mode`, `Puerto USB 2.0 High-Speed OTG (${serie.usb}) para emulación HID, CDC y modo Host`, `Port USB 2.0 High-Speed OTG (${serie.usb}) pour émulation HID, CDC et mode Hôte`, `USB 2.0 High-Speed OTG-Anschluss (${serie.usb}) für HID-, CDC-Emulation und Host-Modus`, `USB 2.0 高速 OTG 端口(${serie.usb}),支持 HID 模拟、CDC 和主机模式`));
|
||
} else if (serie.usb && String(serie.usb).includes("OTG")) {
|
||
scores[key] += 30;
|
||
reasons[key].push(r(`Interface USB OTG 1.1 integrada (${serie.usb}) para emulação HID e Host`, `Integrated USB OTG 1.1 interface (${serie.usb}) for HID emulation and Host mode`, `Interfaz USB OTG 1.1 integrada (${serie.usb}) para emulación HID y Host`, `Interface USB OTG 1.1 intégrée (${serie.usb}) pour émulation HID et mode Hôte`, `Integrierte USB OTG 1.1-Schnittstelle (${serie.usb}) für HID-Emulation und Host-Modus`, `集成 USB OTG 1.1 接口(${serie.usb}),支持 HID 模拟和主机模式`));
|
||
} else {
|
||
scores[key] -= 160;
|
||
alerts[key].push(r("Incompatível: Sem USB OTG nativo (USB Serial/JTAG não suporta modo Host ou HID customizado)", "Incompatible: No native USB OTG (USB Serial/JTAG does not support Host mode or custom HID)", "Incompatible: Sin USB OTG nativo (USB Serial/JTAG no admite modo Host ni HID personalizado)", "Incompatible : Aucun USB OTG natif (USB Serial/JTAG ne prend pas en charge le mode Hôte ou HID personnalisé)", "Inkompatibel: Kein natives USB OTG (USB Serial/JTAG unterstützt keinen Host-Modus oder benutzerdefiniertes HID)", "不兼容:没有原生 USB OTG(USB Serial/JTAG 不支持主机模式或自定义 HID)"));
|
||
}
|
||
} else if (answers.hardware === "can_twai") {
|
||
if (serie.can && String(serie.can).includes("CAN FD")) {
|
||
scores[key] += 40;
|
||
reasons[key].push(r("Controlador avançado CAN-FD (Flexible Data-Rate) para alta largura de banda automotiva", "Advanced CAN-FD (Flexible Data-Rate) controller for automotive high bandwidth", "Controlador avanzado CAN-FD (Flexible Data-Rate) para gran ancho de banda automotriz", "Contrôleur CAN-FD avancé (Flexible Data-Rate) pour haute bande passante automobile", "Fortschrittlicher CAN-FD-Controller (Flexible Data-Rate) für hohe Automobil-Bandbreite", "先进的 CAN-FD(灵活数据速率)控制器,适合车载高带宽场景"));
|
||
} else if (serie.can) {
|
||
scores[key] += 30;
|
||
reasons[key].push(r(`Controlador de barramento industrial ${serie.can}`, `Industrial bus controller ${serie.can}`, `Controlador de bus industrial ${serie.can}`, `Contrôleur de bus industriel ${serie.can}`, `Industrieller Bus-Controller ${serie.can}`, `工业总线控制器 ${serie.can}`));
|
||
} else {
|
||
scores[key] -= 150;
|
||
alerts[key].push(r("Incompatível: Sem controlador de barramento CAN / TWAI nativo", "Incompatible: No native CAN / TWAI bus controller", "Incompatible: Sin controlador de bus CAN / TWAI nativo", "Incompatible : Aucun contrôleur de bus CAN / TWAI natif", "Inkompatibel: Kein nativer CAN / TWAI-Bus-Controller", "不兼容:没有原生 CAN / TWAI 总线控制器"));
|
||
}
|
||
} else if (answers.hardware === "dac_audio") {
|
||
if (!ehNao(serie.dac)) {
|
||
scores[key] += 45;
|
||
reasons[key].push(r(`Conversores Digital-Analógico embutidos (${serie.dac}) para saída de áudio direta sem DAC externo`, `Built-in Digital-to-Analog converters (${serie.dac}) for direct audio output without external DAC`, `Conversores digital-analógico integrados (${serie.dac}) para salida de audio directa sin DAC externo`, `Convertisseurs numérique-analogique intégrés (${serie.dac}) pour sortie audio directe sans DAC externe`, `Integrierte Digital-Analog-Wandler (${serie.dac}) für direkte Audioausgabe ohne externen DAC`, `内置数模转换器(${serie.dac}),无需外部 DAC 即可直接输出音频`));
|
||
} else {
|
||
scores[key] -= 150;
|
||
alerts[key].push(r("Incompatível: Não possui conversor DAC interno de áudio (requer codec I2S externo)", "Incompatible: No internal audio DAC converter (requires external I2S codec)", "Incompatible: No cuenta con conversor DAC de audio interno (requiere códec I2S externo)", "Incompatible : Ne dispose pas de convertisseur DAC audio interne (requiert un codec I2S externe)", "Inkompatibel: Verfügt über keinen internen Audio-DAC (erfordert externen I2S-Codec)", "不兼容:没有内部音频 DAC(需要外部 I2S 编解码器)"));
|
||
}
|
||
} else if (answers.hardware === "many_gpios") {
|
||
const gpios = parseInt(serie.gpio) || 0;
|
||
if (gpios >= 40) {
|
||
scores[key] += 35;
|
||
reasons[key].push(r(`Excepcional número de pinos disponíveis (${gpios} GPIOs)`, `Exceptional number of available pins (${gpios} GPIOs)`, `Excepcional cantidad de pines disponíveis (${gpios} GPIOs)`, `Nombre exceptionnel de broches disponibles (${gpios} GPIO)`, `Außergewöhnlich hohe Anzahl verfügbarer Pins (${gpios} GPIOs)`, `可用引脚数量出众(${gpios} 个 GPIO)`));
|
||
} else if (gpios >= 28) {
|
||
scores[key] += 15;
|
||
reasons[key].push(r(`Quantidade moderada de portas (${gpios} GPIOs)`, `Moderate pin count (${gpios} GPIOs)`, `Cantidad moderada de puertos (${gpios} GPIOs)`, `Nombre modéré de broches (${gpios} GPIO)`, `Moderate Anzahl an Anschlüssen (${gpios} GPIOs)`, `引脚数量适中(${gpios} 个 GPIO)`));
|
||
} else {
|
||
scores[key] -= 60;
|
||
alerts[key].push(r(`Contagem restrita de pinos (${gpios} GPIOs)`, `Restricted pin count (${gpios} GPIOs)`, `Cantidad reducida de pines (${gpios} GPIOs)`, `Nombre restreint de broches (${gpios} GPIO)`, `Eingeschränkte Pin-Anzahl (${gpios} GPIOs)`, `引脚数量有限(${gpios} 个 GPIO)`));
|
||
}
|
||
} else if (answers.hardware === "standard_sensors") {
|
||
scores[key] += 10;
|
||
}
|
||
|
||
// 5. MEMÓRIA & PSRAM (memory)
|
||
if (answers.memory === "heavy_psram") {
|
||
if (serie.psram_externa && (String(serie.psram_externa).includes("64 MB") || String(serie.psram_externa).includes("1 GB"))) {
|
||
scores[key] += 40;
|
||
reasons[key].push(r(`Expansão massiva de memória PSRAM (${serie.psram_externa})`, `Massive PSRAM memory expansion (${serie.psram_externa})`, `Expansión masiva de memoria PSRAM (${serie.psram_externa})`, `Extension massive de mémoire PSRAM (${serie.psram_externa})`, `Massive PSRAM-Speichererweiterung (${serie.psram_externa})`, `PSRAM 大幅扩展(${serie.psram_externa})`));
|
||
} else if (!ehNao(serie.psram_externa)) {
|
||
scores[key] += 25;
|
||
reasons[key].push(r(`Suporte a memória PSRAM externa (${serie.psram_externa})`, `Support for external PSRAM memory (${serie.psram_externa})`, `Soporte para memoria PSRAM externa (${serie.psram_externa})`, `Prise en charge de la mémoire PSRAM externe (${serie.psram_externa})`, `Unterstützung für externen PSRAM-Speicher (${serie.psram_externa})`, `支持外部 PSRAM(${serie.psram_externa})`));
|
||
} else {
|
||
scores[key] -= 180;
|
||
alerts[key].push(r("Incompatível: Sem suporte a memória PSRAM externa ou integrada", "Incompatible: No support for external or integrated PSRAM", "Incompatible: Sin soporte para memoria PSRAM externa o integrada", "Incompatible : Aucune prise en charge de mémoire PSRAM externe ou intégrée", "Inkompatibel: Keine Unterstützung für externen oder integrierten PSRAM", "不兼容:不支持外部或集成 PSRAM"));
|
||
}
|
||
} else if (answers.memory === "moderate_sram") {
|
||
const sramMatch = serie.memoria_sram?.match(/(\d+)\s*KB/);
|
||
if (sramMatch && parseInt(sramMatch[1]) >= 380) {
|
||
scores[key] += 15;
|
||
reasons[key].push(r(`SRAM interna confortável (${serie.memoria_sram})`, `Comfortable internal SRAM (${serie.memoria_sram})`, `SRAM interna amplia (${serie.memoria_sram})`, `SRAM interne confortable (${serie.memoria_sram})`, `Komfortabler interner SRAM (${serie.memoria_sram})`, `内部 SRAM 充裕(${serie.memoria_sram})`));
|
||
} else {
|
||
scores[key] += 8;
|
||
}
|
||
} else if (answers.memory === "minimal_cost") {
|
||
if (key === "ESP32-C2" || key === "ESP32-C3" || key === "ESP32-H2") {
|
||
scores[key] += 25;
|
||
reasons[key].push(r("Memória enxuta e silício compacto para menor custo unitário", "Lean memory and compact silicon for lower unit cost", "Memoria reducida y silicio compacto para menor costo unitario", "Mémoire optimisée et silicium compact pour un coût unitaire réduit", "Schlanker Speicher und kompaktes Silizium für geringste Stückkosten", "精简的内存与紧凑的芯片,单价更低"));
|
||
} else {
|
||
scores[key] += 5;
|
||
}
|
||
}
|
||
|
||
// 6. INTELIGÊNCIA ARTIFICIAL (ai)
|
||
if (answers.ai === "ai_vector") {
|
||
if (serie.aceleradores_ia) {
|
||
scores[key] += 45;
|
||
reasons[key].push(r("Acelerador neural de silício e instruções vetoriais para inferência veloz", "Silicon neural accelerator and vector instructions for fast inference", "Acelerador neuronal de silicio e instrucciones vectoriales para inferencia rápida", "Accélérateur neuronal en silicium et instructions vectorielles pour une inférence rapide", "Silizium-basierter neuronaler Beschleuniger und Vektorbefehle für schnelle Inferenz", "芯片内的神经网络加速器和向量指令,推理速度快"));
|
||
} else {
|
||
scores[key] -= 180;
|
||
alerts[key].push(r("Incompatível: Sem aceleração vetorial por hardware para IA na borda", "Incompatible: No hardware vector acceleration for edge AI", "Incompatible: Sin aceleración vectorial por hardware para IA en el borde", "Incompatible : Aucune accélération vectorielle matérielle pour l'IA en périphérie", "Inkompatibel: Keine Hardware-Vektorbeschleunigung für Edge-KI", "不兼容:没有用于边缘 AI 的硬件向量加速"));
|
||
}
|
||
} else if (answers.ai === "standard") {
|
||
scores[key] += 5;
|
||
}
|
||
|
||
// 7. SEGURANÇA (security)
|
||
const temECDSA = comecaSim(seg.ecdsa);
|
||
const temECC = comecaSim(seg.ecc);
|
||
const temAES = String(seg.aes).startsWith("AES");
|
||
const temKeyManager = ehSim(seg.key_manager);
|
||
const temDPA = ehSim(seg.protecao_dpa);
|
||
|
||
if (answers.security === "key_manager_dpa") {
|
||
if (temKeyManager && temDPA) {
|
||
scores[key] += 45;
|
||
reasons[key].push(r("Key Manager em silício (chaves isoladas da CPU) e proteção contra análise de consumo DPA", "Silicon Key Manager (keys isolated from CPU) and DPA side-channel protection", "Key Manager en silicio (claves aisladas de la CPU) y protección contra análisis de consumo DPA", "Key Manager en silicium (clés isolées du CPU) et protection DPA contre l'analyse de consommation", "Silizium-Key-Manager (Schlüssel isoliert von CPU) und DPA-Seitenkanalschutz", "芯片内密钥管理器(密钥与 CPU 隔离)和 DPA 侧信道防护"));
|
||
} else if (temKeyManager) {
|
||
scores[key] += 35;
|
||
reasons[key].push(r("Periférico Key Manager integrado para isolamento total de chaves privadas", "Integrated Key Manager peripheral for complete private key isolation", "Periférico Key Manager integrado para aislamiento total de claves privadas", "Périphérique Key Manager intégré pour l'isolation totale des clés privées", "Integriertes Key-Manager-Peripheriegerät zur vollständigen Isolation privater Schlüssel", "集成密钥管理器外设,可完全隔离私钥"));
|
||
} else if (temDPA) {
|
||
scores[key] += 20;
|
||
reasons[key].push(r("Proteção física DPA em hardware contra ataques de canal lateral", "Hardware DPA physical protection against side-channel attacks", "Protección física DPA en hardware contra ataques de canal lateral", "Protection matérielle physique DPA contre les attaques par canaux auxiliaires", "Physikalischer DPA-Hardwareschutz gegen Seitenkanalangriffe", "硬件 DPA 物理防护,抵御侧信道攻击"));
|
||
} else {
|
||
scores[key] -= 160;
|
||
alerts[key].push(r("Incompatível: Sem Key Manager nem proteção física contra DPA", "Incompatible: No Key Manager or physical DPA protection", "Incompatible: Sin Key Manager ni protección física contra DPA", "Incompatible : Ni Key Manager ni protection physique contre la DPA", "Inkompatibel: Weder Key Manager noch physikalischer DPA-Schutz vorhanden", "不兼容:没有密钥管理器或物理 DPA 防护"));
|
||
}
|
||
} else if (answers.security === "hardware_ecc_ecdsa") {
|
||
if (temECDSA) {
|
||
scores[key] += 40;
|
||
reasons[key].push(r(`Acelerador de assinatura digital ECDSA determinístico em hardware (${seg.ecc})`, `Deterministic hardware ECDSA digital signature accelerator (${seg.ecc})`, `Acelerador de firma digital ECDSA determinista en hardware (${seg.ecc})`, `Accélérateur de signature numérique ECDSA déterministe en matériel (${seg.ecc})`, `Deterministischer Hardware-ECDSA-Digitalsignatur-Beschleuniger (${seg.ecc})`, `确定性的硬件 ECDSA 数字签名加速器(${seg.ecc})`));
|
||
} else if (temECC) {
|
||
scores[key] += 30;
|
||
reasons[key].push(r(`Coprocessador de curvas elípticas ECC em hardware (${seg.ecc})`, `Hardware ECC elliptic curve coprocessor (${seg.ecc})`, `Coprocesador de curvas elípticas ECC en hardware (${seg.ecc})`, `Coprocesseur matériel pour courbes elliptiques ECC (${seg.ecc})`, `Hardware-Coprozessor für elliptische Kurven (ECC) (${seg.ecc})`, `硬件 ECC 椭圆曲线协处理器(${seg.ecc})`));
|
||
} else {
|
||
scores[key] -= 220;
|
||
alerts[key].push(r("Incompatível: Não possui acelerador de hardware para curvas elípticas (ECC/ECDSA)", "Incompatible: No hardware accelerator for elliptic curves (ECC/ECDSA)", "Incompatible: No cuenta con acelerador de hardware para curvas elípticas (ECC/ECDSA)", "Incompatible : Ne possède aucun accélérateur matériel pour courbes elliptiques (ECC/ECDSA)", "Inkompatibel: Verfügt über keinen Hardwarebeschleuniger für elliptische Kurven (ECC/ECDSA)", "不兼容:没有椭圆曲线(ECC/ECDSA)硬件加速器"));
|
||
}
|
||
} else if (answers.security === "secure_boot") {
|
||
if (String(seg.secure_boot).includes("V2")) {
|
||
scores[key] += 25;
|
||
reasons[key].push(r(`Secure Boot ${seg.secure_boot} com criptografia de flash ${seg.criptografia_flash}`, `Secure Boot ${seg.secure_boot} with flash encryption ${seg.criptografia_flash}`, `Secure Boot ${seg.secure_boot} con cifrado de flash ${seg.criptografia_flash}`, `Démarrage sécurisé ${seg.secure_boot} avec chiffrement Flash ${seg.criptografia_flash}`, `Secure Boot ${seg.secure_boot} mit Flash-Verschlüsselung ${seg.criptografia_flash}`, `安全启动 ${seg.secure_boot},闪存加密 ${seg.criptografia_flash}`));
|
||
} else if (String(seg.secure_boot).includes("V1")) {
|
||
scores[key] += 5;
|
||
alerts[key].push(r("Secure Boot em esquema V1 (legado com limitações de segurança)", "Secure Boot V1 scheme (legacy with security limitations)", "Secure Boot en esquema V1 (heredado con limitaciones de seguridad)", "Démarrage sécurisé en schéma V1 (hérité avec limitations de sécurité)", "Secure Boot im V1-Schema (veraltet mit Sicherheitseinschränkungen)", "安全启动 V1 方案(旧版,存在安全局限)"));
|
||
} else {
|
||
scores[key] -= 80;
|
||
alerts[key].push(r("Sem Secure Boot V2 estável", "No stable Secure Boot V2", "Sin Secure Boot V2 estable", "Aucun démarrage sécurisé V2 stable", "Kein stabiles Secure Boot V2", "没有稳定的安全启动 V2"));
|
||
}
|
||
} else if (answers.security === "standard_tls") {
|
||
if (temAES) {
|
||
scores[key] += 15;
|
||
reasons[key].push(r(`Criptografia de tráfego TLS acelerada por hardware (${seg.aes})`, `Hardware-accelerated TLS traffic encryption (${seg.aes})`, `Cifrado de tráfico TLS acelerado por hardware (${seg.aes})`, `Chiffrement du trafic TLS accéléré matériellement (${seg.aes})`, `Hardwarebeschleunigte TLS-Datenverkehrsverschlüsselung (${seg.aes})`, `硬件加速的 TLS 流量加密(${seg.aes})`));
|
||
} else {
|
||
scores[key] += 5;
|
||
}
|
||
}
|
||
|
||
// 8. ECOSSISTEMA (ecosystem)
|
||
if (answers.ecosystem === "arduino_ready") {
|
||
if (comecaSim(serie.arduino_core)) {
|
||
const countMatch = serie.arduino_core.match(/(\d+)\s*(?:definições|board|definitions|definiciones|définitions|Definitionen|个板卡)/);
|
||
const count = countMatch ? parseInt(countMatch[1]) : 1;
|
||
if (count >= 20) {
|
||
scores[key] += 25;
|
||
reasons[key].push(r(`Excelente maturidade no core oficial Arduino (${count} variantes de placas)`, `Excellent maturity in the official Arduino core (${count} board variants)`, `Excelente madurez en el core oficial de Arduino (${count} variantes de placas)`, `Excellente maturité dans le core officiel Arduino (${count} variantes de cartes)`, `Hervorragende Reife im offiziellen Arduino-Core (${count} Board-Varianten)`, `官方 Arduino 核心的成熟度极高(${count} 个板卡变体)`));
|
||
} else {
|
||
scores[key] += 15;
|
||
reasons[key].push(r(`Suporte no core oficial Arduino (${count} placa registrada)`, `Support in the official Arduino core (${count} registered board)`, `Soporte en el core oficial de Arduino (${count} placa registrada)`, `Prise en charge dans le core officiel Arduino (${count} carte enregistrée)`, `Unterstützung im offiziellen Arduino-Core (${count} registriertes Board)`, `官方 Arduino 核心已支持(已登记 ${count} 个板卡)`));
|
||
}
|
||
} else {
|
||
scores[key] -= 200;
|
||
alerts[key].push(r("Incompatível: Ainda não suportado no core oficial do Arduino (desenvolvimento restrito ao ESP-IDF)", "Incompatible: Not yet supported in the official Arduino core (development restricted to ESP-IDF)", "Incompatible: Aún no soportado en el core oficial de Arduino (desarrollo restringido a ESP-IDF)", "Incompatible : Pas encore pris en charge dans le core officiel Arduino (développement limité à l'ESP-IDF)", "Inkompatibel: Im offiziellen Arduino-Core noch nicht unterstützt (Entwicklung auf ESP-IDF beschränkt)", "不兼容:官方 Arduino 核心尚未支持(开发仅限 ESP-IDF)"));
|
||
}
|
||
} else if (answers.ecosystem === "advanced_idf") {
|
||
scores[key] += 15;
|
||
}
|
||
});
|
||
|
||
return { scores, reasons, alerts };
|
||
};
|
||
|
||
// Parametric Direct Filter Matcher
|
||
const filteredChips = useMemo(() => {
|
||
if (mode !== "filter") return [];
|
||
|
||
return Object.entries(seriesData).filter(([_, serie]) => {
|
||
const seg = serie.seguranca || {};
|
||
const hasMatter = ehSim(serie.matter);
|
||
|
||
if (filters.wifi6 && !String(serie.wifi).includes("Wi-Fi 6") && !String(serie.wifi).includes("802.11ax")) return false;
|
||
if (filters.wifi5ghz && (!serie.wifi || !String(serie.wifi).includes("5 GHz"))) return false;
|
||
if (filters.bluetoothClassic && (!serie.bluetooth || !/Classic|Clássico|Clásico|Classique|Klassisch|经典/.test(String(serie.bluetooth)))) return false;
|
||
if (filters.leAudio && (!serie.bluetooth || !String(serie.bluetooth).includes("LE Audio"))) return false;
|
||
if (filters.matter && !hasMatter) return false;
|
||
if (filters.ethernet && !serie.ethernet && !serie.ethernet_mac) return false;
|
||
if (filters.aiAccel && !serie.aceleradores_ia) return false;
|
||
if (filters.psram && (ehNao(serie.psram_externa))) return false;
|
||
if (filters.mipiDisplayCamera && !serie.mipi_dsi && !serie.mipi_csi && !serie.lcd && !serie.camera) return false;
|
||
if (filters.usbOTG && (!serie.usb || !String(serie.usb).includes("OTG"))) return false;
|
||
if (filters.canBus && !serie.can) return false;
|
||
if (filters.dac && (ehNao(serie.dac))) return false;
|
||
if (filters.touch && (ehNao(serie.touch))) return false;
|
||
if (filters.arduinoReady && (!serie.arduino_core || !comecaSim(serie.arduino_core))) return false;
|
||
if (filters.keyManager && !ehSim(seg.key_manager)) return false;
|
||
if (filters.eccHardware && ehNao(seg.ecc)) return false;
|
||
if (filters.ecdsaHardware && (!seg.ecdsa || !comecaSim(seg.ecdsa))) return false;
|
||
if (filters.secureBootV2 && (!seg.secure_boot || !String(seg.secure_boot).includes("V2"))) return false;
|
||
|
||
return true;
|
||
});
|
||
}, [mode, filters, seriesData]);
|
||
|
||
const { scores: allScores, reasons: allReasons, alerts: allAlerts } = useMemo(() => {
|
||
if (showResults && Object.values(answers).every(a => a !== null)) {
|
||
return calculateRecommendations();
|
||
}
|
||
return { scores: {}, reasons: {}, alerts: {} };
|
||
}, [showResults, answers, seriesData]);
|
||
|
||
const recommendations = useMemo(() => {
|
||
const entries = Object.entries(allScores)
|
||
.filter(([_, score]) => score > 0)
|
||
.sort(([, a], [, b]) => b - a);
|
||
|
||
const maxScore = entries.length > 0 ? entries[0][1] : 1;
|
||
|
||
return entries.map(([key, score]) => ({
|
||
key,
|
||
score,
|
||
percentage: Math.min(100, Math.round((score / maxScore) * 100)),
|
||
}));
|
||
}, [allScores]);
|
||
|
||
const topThree = recommendations.slice(0, 3);
|
||
const otherRecommendations = recommendations.slice(3);
|
||
|
||
const progress = ((currentStep + 1) / questions.length) * 100;
|
||
|
||
const filtrosAtivos = FILTROS.filter(({ key }) => filters[key]).length;
|
||
const limparFiltros = () => setFilters(Object.fromEntries(FILTROS.map(({ key }) => [key, false])));
|
||
|
||
// O texto das perguntas vem numerado ("1. Qual é..."); a interface já mostra a etapa.
|
||
const semNumero = (texto) => texto.replace(/^\d+\.\s*/, "");
|
||
|
||
const pergunta = questions[currentStep];
|
||
|
||
return (
|
||
<div className="site-canvas min-h-screen">
|
||
<Header />
|
||
|
||
<main id="conteudo">
|
||
<PageHero
|
||
isEn={isEn}
|
||
isEs={isEs}
|
||
isFr={isFr}
|
||
isDe={isDe} isZh={isZh}
|
||
trail={
|
||
isZh ? [{ label: "芯片选型" }] : isDe
|
||
? [{ label: "Chip-Auswahl" }]
|
||
: isFr
|
||
? [{ label: "Sélecteur de puce" }]
|
||
: isEs
|
||
? [{ label: "Selector de chips" }]
|
||
: isEn
|
||
? [{ label: "Chip selector" }]
|
||
: [{ label: "Seletor de chip" }]
|
||
}
|
||
icon={Sparkles}
|
||
label={
|
||
isZh ? "智能选型" : isDe
|
||
? "Intelligente Auswahl"
|
||
: isFr
|
||
? "Sélecteur intelligent"
|
||
: isEs
|
||
? "Selector inteligente"
|
||
: isEn
|
||
? "Smart selector"
|
||
: "Seletor inteligente"
|
||
}
|
||
title={
|
||
isZh ? "该选哪款 ESP32?" : isDe
|
||
? "Welchen ESP32 wählen?"
|
||
: isFr
|
||
? "Quel ESP32 choisir ?"
|
||
: isEs
|
||
? "¿Qué ESP32 elegir?"
|
||
: isEn
|
||
? "Which ESP32 to choose?"
|
||
: "Qual ESP32 escolher?"
|
||
}
|
||
lede={
|
||
isZh ? "回答八个关于项目的问题,或勾选所需功能,找到最匹配的型号及其技术依据。" : isDe
|
||
? "Beantworten Sie acht Fragen zu Ihrem Projekt oder wählen Sie erforderliche Funktionen, um die am besten passenden Modelle mit technischer Begründung zu finden."
|
||
: isFr
|
||
? "Répondez à huit questions sur votre projet, ou cochez les fonctionnalités requises, pour trouver les modèles les plus compatibles avec justification technique."
|
||
: isEs
|
||
? "Responda a ocho preguntas sobre su proyecto, o marque las funciones obligatorias, y vea los modelos más compatibles con su justificación técnica."
|
||
: isEn
|
||
? "Answer eight questions about your project, or select required features, to find the best matching models with technical rationale."
|
||
: "Responda a oito perguntas sobre o projeto, ou marque os recursos obrigatórios, e veja os modelos mais compatíveis com a justificativa técnica."
|
||
}
|
||
>
|
||
<div
|
||
role="group"
|
||
aria-label={
|
||
isZh ? "选型模式" : isDe
|
||
? "Auswahlmodus"
|
||
: isFr
|
||
? "Mode de sélection"
|
||
: isEs
|
||
? "Modo de selección"
|
||
: isEn
|
||
? "Selection mode"
|
||
: "Modo de seleção"
|
||
}
|
||
className="flex flex-wrap gap-2"
|
||
>
|
||
<button type="button" onClick={() => setMode("wizard")} aria-pressed={mode === "wizard"} className="chip-btn">
|
||
<Sparkles className="h-4 w-4" aria-hidden="true" />
|
||
{isZh ? "引导向导" : isDe ? "Geführter Assistent" : isFr ? "Assistant guidé" : isEs ? "Asistente guiado" : isEn ? "Guided wizard" : "Assistente guiado"}
|
||
</button>
|
||
<button type="button" onClick={() => setMode("filter")} aria-pressed={mode === "filter"} className="chip-btn">
|
||
<Filter className="h-4 w-4" aria-hidden="true" />
|
||
{isZh ? "功能筛选" : isDe ? "Funktionsfilter" : isFr ? "Filtre par fonctionnalités" : isEs ? "Filtro por recursos" : isEn ? "Feature filter" : "Filtro por recursos"}
|
||
</button>
|
||
</div>
|
||
</PageHero>
|
||
|
||
{/* Assistente: pergunta */}
|
||
{mode === "wizard" && !showResults && !showSummary && (
|
||
<section className="shell pb-6 pt-10" aria-labelledby="pergunta-titulo">
|
||
<div className="panel mx-auto max-w-3xl p-5 sm:p-9">
|
||
<div className="flex items-center justify-between gap-4 text-sm">
|
||
<p className="font-medium text-ink">
|
||
{isZh ? ( <>第 {currentStep + 1} 步,共 {questions.length} 步</> ) : isDe ? (
|
||
<>Schritt {currentStep + 1} von {questions.length}</>
|
||
) : isFr ? (
|
||
<>Étape {currentStep + 1} sur {questions.length}</>
|
||
) : isEs ? (
|
||
<>Paso {currentStep + 1} de {questions.length}</>
|
||
) : isEn ? (
|
||
<>Step {currentStep + 1} of {questions.length}</>
|
||
) : (
|
||
<>Etapa {currentStep + 1} de {questions.length}</>
|
||
)}
|
||
<span className="text-muted"> · {ROTULOS_ETAPA[pergunta.id]}</span>
|
||
</p>
|
||
<span className="tabular-nums text-muted">{Math.round(progress)}%</span>
|
||
</div>
|
||
<div
|
||
role="progressbar"
|
||
aria-valuemin={0}
|
||
aria-valuemax={100}
|
||
aria-valuenow={Math.round(progress)}
|
||
aria-label={isZh ? "问卷进度" : isDe ? "Fortschritt des Fragebogens" : isFr ? "Progression du questionnaire" : isEs ? "Progreso del cuestionario" : isEn ? "Quiz progress" : "Progresso do questionário"}
|
||
className="mt-3 h-1.5 overflow-hidden rounded-full bg-line"
|
||
>
|
||
<div className="h-full rounded-full bg-accent transition-[width] duration-500 ease-out" style={{ width: `${progress}%` }} />
|
||
</div>
|
||
|
||
<h2 id="pergunta-titulo" className="section-title mt-8">{semNumero(pergunta.question)}</h2>
|
||
<p className="mt-3 text-sm leading-relaxed text-muted sm:text-base">{pergunta.description}</p>
|
||
|
||
<div role="radiogroup" aria-labelledby="pergunta-titulo" className="mt-7 grid gap-2.5">
|
||
{pergunta.options.map((option) => {
|
||
const isSelected = currentAnswer === option.value;
|
||
return (
|
||
<button
|
||
key={option.value}
|
||
type="button"
|
||
role="radio"
|
||
aria-checked={isSelected}
|
||
onClick={() => handleAnswer(pergunta.id, option.value)}
|
||
className={`flex min-h-14 items-center gap-4 rounded-xl border p-3.5 text-left transition-colors sm:p-4 ${
|
||
isSelected ? "border-accent bg-accent-soft" : "border-line-strong bg-surface hover:bg-surface-2"
|
||
}`}
|
||
>
|
||
<span className={`grid h-10 w-10 shrink-0 place-items-center rounded-full ${isSelected ? "bg-accent text-accent-contrast" : "bg-surface-2 text-accent"}`}>
|
||
{getOptionIcon(pergunta.id, option.value)}
|
||
</span>
|
||
<span className="grow text-sm font-medium leading-snug text-ink sm:text-base">{option.label}</span>
|
||
{isSelected && <Check className="h-5 w-5 shrink-0 text-accent" aria-hidden="true" />}
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
|
||
<div className="mt-8 flex flex-col-reverse items-stretch gap-3 border-t border-line pt-6 sm:flex-row sm:items-center sm:justify-between">
|
||
<button type="button" onClick={goBack} disabled={currentStep === 0} className="btn btn-ghost disabled:cursor-not-allowed disabled:opacity-40">
|
||
<ChevronLeft className="h-4 w-4" aria-hidden="true" />
|
||
{isZh ? "上一步" : isDe ? "Zurück" : isFr ? "Retour" : isEs ? "Volver" : isEn ? "Back" : "Voltar"}
|
||
</button>
|
||
<button type="button" onClick={resetQuiz} className="inline-flex min-h-11 items-center justify-center gap-1.5 text-sm font-medium text-muted hover:text-ink">
|
||
<RotateCcw className="h-4 w-4" aria-hidden="true" />
|
||
{isZh ? "重新开始" : isDe ? "Neu starten" : isFr ? "Recommencer" : isEs ? "Reiniciar" : isEn ? "Restart" : "Recomeçar"}
|
||
</button>
|
||
<button type="button" onClick={handleNext} disabled={currentAnswer === null} className="btn btn-primary disabled:cursor-not-allowed disabled:opacity-40">
|
||
{currentStep === questions.length - 1
|
||
? (isZh ? "查看答案" : isDe ? "Antworten prüfen" : isFr ? "Vérifier les réponses" : isEs ? "Revisar respuestas" : isEn ? "Review answers" : "Revisar respostas")
|
||
: (isZh ? "下一步" : isDe ? "Weiter" : isFr ? "Suivant" : isEs ? "Avanzar" : isEn ? "Next" : "Avançar")}
|
||
<ChevronRight className="h-4 w-4" aria-hidden="true" />
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
)}
|
||
|
||
{/* Atalhos por aplicação */}
|
||
{mode === "wizard" && !showResults && !showSummary && currentStep === 0 && (
|
||
<section className="shell pb-6 pt-10" aria-labelledby="atalhos-titulo">
|
||
<h2 id="atalhos-titulo" className="text-base font-semibold text-ink">
|
||
{isZh ? "或从现成的配置方案开始" : isDe ? "Oder mit einem vorgefertigten Profil starten" : isFr ? "Ou commencez par un profil prédéfini" : isEs ? "O comience con un perfil predefinido" : isEn ? "Or start with a ready-made profile" : "Ou comece por um perfil pronto"}
|
||
</h2>
|
||
<p className="mt-1 text-sm text-muted">
|
||
{isZh ? "一次性应用全部八个答案并显示推荐。你可以随时调整。" : isDe
|
||
? "Wendet alle acht Antworten auf einmal an und zeigt das Ergebnis. Sie können diese später anpassen."
|
||
: isFr
|
||
? "Applique les huit réponses d'un coup et affiche le résultat. Vous pouvez les ajuster ensuite."
|
||
: isEs
|
||
? "Aplica las ocho respuestas de una sola vez y muestra el resultado. Puede ajustarlas después."
|
||
: isEn
|
||
? "Applies all eight answers at once and displays recommendations. You can adjust them anytime."
|
||
: "Aplica as oito respostas de uma vez e mostra o resultado. Você pode ajustar depois."}
|
||
</p>
|
||
<div className="mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
||
{PRESETS.map((preset) => (
|
||
<button
|
||
key={preset.id}
|
||
type="button"
|
||
onClick={() => applyPreset(preset)}
|
||
className="card card-interactive group flex items-start gap-4 p-4 text-left sm:p-5"
|
||
>
|
||
<span className="grid h-10 w-10 shrink-0 place-items-center rounded-full bg-accent-soft text-accent">
|
||
{iconMap[`category_${preset.answers.category}`] || <Sparkles className="h-5 w-5" aria-hidden="true" />}
|
||
</span>
|
||
<span className="min-w-0">
|
||
<span className="block font-semibold text-ink">{preset.title}</span>
|
||
<span className="mt-0.5 block text-sm text-muted">{preset.description}</span>
|
||
<span className="mt-2 inline-flex items-center gap-1 text-sm font-medium text-accent">
|
||
{isZh ? "查看推荐" : isDe ? "Empfehlung ansehen" : isFr ? "Voir la recommandation" : isEs ? "Ver recomendación" : isEn ? "View recommendation" : "Ver recomendação"}
|
||
<ArrowRight className="h-3.5 w-3.5 transition-transform group-hover:translate-x-0.5" aria-hidden="true" />
|
||
</span>
|
||
</span>
|
||
</button>
|
||
))}
|
||
</div>
|
||
</section>
|
||
)}
|
||
|
||
{/* Assistente: revisão */}
|
||
{mode === "wizard" && showSummary && !showResults && (
|
||
<section className="shell pb-6 pt-10" aria-labelledby="resumo-titulo">
|
||
<div className="panel mx-auto max-w-4xl p-5 sm:p-9">
|
||
<h2 id="resumo-titulo" className="section-title">
|
||
{isZh ? "查看你的答案" : isDe ? "Überprüfen Sie Ihre Antworten" : isFr ? "Vérifiez vos réponses" : isEs ? "Revise sus respuestas" : isEn ? "Review your answers" : "Revise suas respostas"}
|
||
</h2>
|
||
<p className="mt-3 text-sm text-muted sm:text-base">
|
||
{isZh ? "在计算各系列的兼容度之前,请先确认你的选择。" : isDe
|
||
? "Überprüfen Sie Ihre Auswahl vor der Berechnung der Kompatibilität für jede Serie."
|
||
: isFr
|
||
? "Vérifiez vos choix avant de calculer la compatibilité avec chaque série."
|
||
: isEs
|
||
? "Revise sus elecciones antes de calcular la compatibilidad con cada serie."
|
||
: isEn
|
||
? "Review your choices before computing compatibility for each series."
|
||
: "Confira as escolhas antes de calcular a compatibilidade com cada série."}
|
||
</p>
|
||
|
||
<ul className="mt-7 grid gap-3 md:grid-cols-2">
|
||
{questions.map((question) => {
|
||
const answer = answers[question.id];
|
||
const selectedOption = question.options.find((opt) => opt.value === answer);
|
||
return (
|
||
<li key={question.id} className="tile flex items-start justify-between gap-3">
|
||
<div className="min-w-0">
|
||
<p className="text-xs font-medium text-muted">{ROTULOS_ETAPA[question.id]}</p>
|
||
{selectedOption && <p className="mt-1 text-sm font-medium leading-snug text-ink">{selectedOption.label}</p>}
|
||
</div>
|
||
<button
|
||
type="button"
|
||
onClick={() => {
|
||
setCurrentStep(questions.findIndex((q) => q.id === question.id));
|
||
setCurrentAnswer(answers[question.id]);
|
||
setShowSummary(false);
|
||
}}
|
||
className="grid h-11 w-11 shrink-0 place-items-center rounded-full text-muted transition-colors hover:bg-surface hover:text-accent"
|
||
aria-label={isZh ? `修改答案:${ROTULOS_ETAPA[question.id]}` : isDe ? `Antwort bearbeiten: ${ROTULOS_ETAPA[question.id]}` : isFr ? `Modifier la réponse : ${ROTULOS_ETAPA[question.id]}` : isEs ? `Editar respuesta: ${ROTULOS_ETAPA[question.id]}` : isEn ? `Edit answer: ${ROTULOS_ETAPA[question.id]}` : `Editar resposta: ${ROTULOS_ETAPA[question.id]}`}
|
||
>
|
||
<Edit2 className="h-4 w-4" aria-hidden="true" />
|
||
</button>
|
||
</li>
|
||
);
|
||
})}
|
||
</ul>
|
||
|
||
<div className="mt-8 flex flex-col-reverse gap-3 border-t border-line pt-6 sm:flex-row sm:justify-between">
|
||
<button
|
||
type="button"
|
||
onClick={() => {
|
||
setCurrentStep(questions.length - 1);
|
||
setCurrentAnswer(answers[questions[questions.length - 1].id]);
|
||
setShowSummary(false);
|
||
}}
|
||
className="btn btn-ghost"
|
||
>
|
||
<ChevronLeft className="h-4 w-4" aria-hidden="true" />
|
||
{isZh ? "上一步" : isDe ? "Zurück" : isFr ? "Retour" : isEs ? "Volver" : isEn ? "Back" : "Voltar"}
|
||
</button>
|
||
<button type="button" onClick={() => setShowResults(true)} className="btn btn-primary">
|
||
<Sparkles className="h-4 w-4" aria-hidden="true" />
|
||
{isZh ? "查看推荐" : isDe ? "Empfehlungen ansehen" : isFr ? "Voir les recommandations" : isEs ? "Ver recomendaciones" : isEn ? "View recommendations" : "Ver recomendações"}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
)}
|
||
|
||
{/* Assistente: resultado */}
|
||
{mode === "wizard" && showResults && recommendations.length > 0 && (
|
||
<section className="shell pb-6 pt-10" aria-labelledby="resultado-titulo">
|
||
<div className="flex flex-col justify-between gap-4 sm:flex-row sm:items-end">
|
||
<div>
|
||
<h2 id="resultado-titulo" className="section-title">
|
||
{isZh ? "你的推荐" : isDe ? "Ihre Empfehlungen" : isFr ? "Vos recommandations" : isEs ? "Sus recomendaciones" : isEn ? "Your recommendations" : "Suas recomendações"}
|
||
</h2>
|
||
<p role="status" className="mt-2 text-sm text-muted">
|
||
{isZh ? `共 ${recommendations.length} 个匹配的型号,按推荐程度从高到低排序。` : isDe
|
||
? `${recommendations.length} passende Modelle, sortiert von am meisten bis am wenigsten empfohlen.`
|
||
: isFr
|
||
? `${recommendations.length} modèles compatibles, du plus au moins recommandé.`
|
||
: isEs
|
||
? `${recommendations.length} modelos compatibles, del más al menos recomendado.`
|
||
: isEn
|
||
? `${recommendations.length} matching models, ranked from most to least recommended.`
|
||
: `${recommendations.length} modelos compatíveis, do mais ao menos indicado.`}
|
||
</p>
|
||
</div>
|
||
<div className="flex flex-wrap gap-2">
|
||
<button type="button" onClick={() => { setShowResults(false); setShowSummary(true); }} className="btn btn-ghost btn-sm">
|
||
<Edit2 className="h-4 w-4" aria-hidden="true" />
|
||
{isZh ? "调整答案" : isDe ? "Antworten anpassen" : isFr ? "Ajuster les réponses" : isEs ? "Ajustar respuestas" : isEn ? "Adjust answers" : "Ajustar respostas"}
|
||
</button>
|
||
<button type="button" onClick={resetQuiz} className="btn btn-ghost btn-sm">
|
||
<RotateCcw className="h-4 w-4" aria-hidden="true" />
|
||
{isEs ? "Reiniciar" : isEn ? "Restart" : "Recomeçar"}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<ol className="mt-8 grid gap-4 lg:grid-cols-3">
|
||
{topThree.map((rec, index) => {
|
||
const seriesKey = rec.key;
|
||
const serie = seriesData[seriesKey];
|
||
const matchReasons = allReasons[seriesKey] || [];
|
||
const chipAlerts = allAlerts[seriesKey] || [];
|
||
const primeiro = index === 0;
|
||
const rankLabel = isZh ? `推荐第 ${index + 1} 名` : isDe
|
||
? `${index + 1}. Empfehlung`
|
||
: isFr
|
||
? `${index + 1}${index === 0 ? "re" : "e"} recommandation`
|
||
: isEs
|
||
? `${index + 1}ª recomendación`
|
||
: isEn
|
||
? `${index + 1}${index === 0 ? "st" : index === 1 ? "nd" : index === 2 ? "rd" : "th"} recommendation`
|
||
: `${index + 1}ª recomendação`;
|
||
return (
|
||
<li key={seriesKey} className={`card flex flex-col p-5 sm:p-6 ${primeiro ? "border-accent ring-2 ring-accent/20" : ""}`}>
|
||
<div className="flex items-center justify-between gap-3">
|
||
<span className={`chip ${primeiro ? "chip-accent" : ""}`}>
|
||
{primeiro && <Award className="h-3.5 w-3.5" aria-hidden="true" />}
|
||
{rankLabel}
|
||
</span>
|
||
<span className="text-sm text-muted">
|
||
{isZh ? "匹配度" : isDe ? "Übereinstimmung" : isFr ? "Affinité" : isEs ? "Afinidad" : isEn ? "Match" : "Afinidade"} <strong className="font-semibold text-ink">{rec.percentage}%</strong>
|
||
</span>
|
||
</div>
|
||
|
||
<h3 className="mt-4 font-display text-2xl font-semibold tracking-[-0.035em] text-ink">{seriesKey}</h3>
|
||
<p className="mt-1 line-clamp-2 text-sm text-muted">{serie.descricao}</p>
|
||
|
||
<div className="mt-5 h-1.5 overflow-hidden rounded-full bg-line" aria-hidden="true">
|
||
<div className="h-full rounded-full bg-accent" style={{ width: `${rec.percentage}%` }} />
|
||
</div>
|
||
|
||
<h4 className="mt-6 text-sm font-semibold text-ink">
|
||
{isZh ? "为什么适合" : isDe ? "Warum es passt" : isFr ? "Pourquoi cela correspond" : isEs ? "Por qué encaja" : isEn ? "Why it fits" : "Por que combina"}
|
||
</h4>
|
||
<ul className="mt-2 space-y-2">
|
||
{matchReasons.slice(0, 3).map((reason) => (
|
||
<li key={reason} className="flex items-start gap-2 text-sm leading-relaxed text-ink-soft">
|
||
<Check className="mt-1 h-3.5 w-3.5 shrink-0 text-ok" aria-hidden="true" />
|
||
{reason}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
|
||
{chipAlerts.length > 0 && (
|
||
<div className="callout callout-warn mt-5">
|
||
<p className="flex items-center gap-1.5 font-semibold text-ink">
|
||
<AlertTriangle className="h-4 w-4 text-gold" aria-hidden="true" />
|
||
{isZh ? "注意事项" : isDe ? "Wichtige Hinweise" : isFr ? "Points d'attention" : isEs ? "Puntos de atención" : isEn ? "Attention points" : "Pontos de atenção"}
|
||
</p>
|
||
<ul className="mt-1.5 list-disc space-y-1 pl-5">
|
||
{chipAlerts.slice(0, 2).map((alert) => (
|
||
<li key={alert}>{alert}</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
)}
|
||
|
||
<dl className="mt-5 grid grid-cols-2 gap-2">
|
||
{[
|
||
[isZh ? "架构" : isDe ? "Architektur" : isFr ? "Architecture" : isEs ? "Arquitectura" : isEn ? "Architecture" : "Arquitetura", serie.arquitetura.split(" ")[0]],
|
||
["Clock", serie.frequencia],
|
||
["GPIO", isZh ? `${serie.gpio} 个引脚` : isDe ? `${serie.gpio} Pins` : isFr ? `${serie.gpio} broches` : isEs ? `${serie.gpio} pines` : isEn ? `${serie.gpio} pins` : `${serie.gpio} pinos`],
|
||
["SRAM", serie.memoria_sram],
|
||
].map(([rotulo, valor]) => (
|
||
<div key={rotulo} className="tile !p-3">
|
||
<dt className="text-xs text-muted">{rotulo}</dt>
|
||
<dd className="mt-0.5 truncate text-sm font-medium text-ink">{valor}</dd>
|
||
</div>
|
||
))}
|
||
</dl>
|
||
|
||
<Link href={getLocalizedHref(`/series/${seriesKey}`, currentLocale)} className={`btn mt-6 w-full ${primeiro ? "btn-primary" : "btn-ghost"}`}>
|
||
{isZh ? `打开 ${seriesKey} 数据手册` : isDe ? `Datenblatt für ${seriesKey} öffnen` : isFr ? `Ouvrir la fiche de ${seriesKey}` : isEs ? `Abrir la ficha de ${seriesKey}` : isEn ? `Open ${seriesKey} datasheet` : `Abrir a ficha do ${seriesKey}`}
|
||
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
|
||
</Link>
|
||
</li>
|
||
);
|
||
})}
|
||
</ol>
|
||
|
||
<div className="panel mt-10 p-5 sm:p-8">
|
||
<div className="flex flex-col justify-between gap-3 sm:flex-row sm:items-center">
|
||
<div>
|
||
<h3 className="font-display text-xl font-semibold tracking-[-0.03em] text-ink">
|
||
{isZh ? "入围的三款并排对比" : isDe ? "Die Finalisten Seite an Seite" : isFr ? "Les finalistes côte à côte" : isEs ? "Los finalistas lado a lado" : isEn ? "The finalists side by side" : "Os finalistas lado a lado"}
|
||
</h3>
|
||
<p className="mt-1 text-sm text-muted">
|
||
{isZh ? "前三名推荐的关键规格。" : isDe
|
||
? "Die wichtigsten Spezifikationen der ersten drei Empfehlungen."
|
||
: isFr
|
||
? "Les principales spécifications des trois premières recommandations."
|
||
: isEs
|
||
? "Las principales especificaciones de las tres primeras recomendaciones."
|
||
: isEn
|
||
? "Key specifications of the top three recommendations."
|
||
: "As principais especificações das três primeiras recomendações."}
|
||
</p>
|
||
</div>
|
||
<Link href={getLocalizedHref(`/comparacao?chips=${topThree.map((t) => t.key).join(",")}`, currentLocale)} className="inline-flex min-h-11 items-center gap-1.5 text-sm font-medium text-accent hover:text-accent-strong">
|
||
{isZh ? "在完整对比中打开" : isDe ? "Im vollständigen Vergleich öffnen" : isFr ? "Ouvrir dans le comparateur complet" : isEs ? "Abrir en el comparador completo" : isEn ? "Open in full comparison" : "Abrir no comparador completo"}
|
||
<ArrowRight className="h-4 w-4" aria-hidden="true" />
|
||
</Link>
|
||
</div>
|
||
|
||
<div className="mt-6 overflow-x-auto">
|
||
<table className="w-full min-w-[32rem] border-collapse text-left text-sm">
|
||
<caption className="sr-only">
|
||
{isZh ? "三个推荐系列的对比" : isDe ? "Vergleich der drei empfohlenen Serien" : isFr ? "Comparaison des trois séries recommandées" : isEs ? "Comparación de las tres series recomendadas" : isEn ? "Comparison of the three recommended series" : "Comparação das três séries recomendadas"}
|
||
</caption>
|
||
<thead>
|
||
<tr className="border-b border-line">
|
||
<th scope="col" className="px-3 py-3 font-medium text-muted">
|
||
{isZh ? "参数" : isDe ? "Parameter" : isFr ? "Paramètre" : isEs ? "Parámetro" : isEn ? "Parameter" : "Parâmetro"}
|
||
</th>
|
||
{topThree.map((rec) => (
|
||
<th key={rec.key} scope="col" className="px-3 py-3 font-display text-base font-semibold text-ink">{rec.key}</th>
|
||
))}
|
||
</tr>
|
||
</thead>
|
||
<tbody className="divide-y divide-line text-ink-soft">
|
||
{[
|
||
[isZh ? "架构" : isDe ? "Architektur" : isFr ? "Architecture" : isEs ? "Arquitectura" : isEn ? "Architecture" : "Arquitetura", (c) => c.arquitetura],
|
||
["Clock", (c) => c.frequencia],
|
||
["Wi-Fi", (c) => c.wifi],
|
||
["Bluetooth", (c) => c.bluetooth],
|
||
["Matter / 802.15.4", (c) => ((c.matter === "Sim" || c.matter === "Yes" || c.matter === "Sí" || c.matter === "Oui" || (c.matter === "Ja" || c.matter === "是")) ? (isZh ? "是" : isDe ? "Ja" : isFr ? "Oui" : isEs ? "Sí" : isEn ? "Yes" : "Sim") : (isZh ? "否" : isDe ? "Nein" : isFr ? "Non" : isEs || isEn ? "No" : "Não"))],
|
||
[isZh ? "AI 加速" : isDe ? "KI-Beschleunigung" : isFr ? "Accélération IA" : isEs ? "Aceleración de IA" : isEn ? "AI Acceleration" : "Aceleração de IA", (c) => (c.aceleradores_ia ? (isZh ? "向量" : isDe ? "Vektoriell" : isFr ? "Vectorielle" : isEs ? "Vectorial" : isEn ? "Vector" : "Vetorial") : (isZh ? "否" : isDe ? "Nein" : isFr ? "Non" : isEs || isEn ? "No" : "Não"))],
|
||
[isZh ? "外部 PSRAM" : isDe ? "Externes PSRAM" : isFr ? "PSRAM externe" : isEs ? "PSRAM externa" : isEn ? "External PSRAM" : "PSRAM externa", (c) => (c.psram_externa && c.psram_externa !== "Não" && c.psram_externa !== "No" && c.psram_externa !== "Non" && (c.psram_externa !== "Nein" && c.psram_externa !== "否") ? c.psram_externa : (isZh ? "否" : isDe ? "Nein" : isFr ? "Non" : isEs || isEn ? "No" : "Não"))],
|
||
["Arduino Core", (c) => ((String(c.arduino_core).startsWith("Sim") || String(c.arduino_core).startsWith("Yes") || String(c.arduino_core).startsWith("Sí") || String(c.arduino_core).startsWith("Oui") || (String(c.arduino_core).startsWith("Ja") || String(c.arduino_core).startsWith("是"))) ? (isZh ? "支持" : isDe ? "Unterstützt" : isFr ? "Pris en charge" : isEs ? "Soportado" : isEn ? "Supported" : "Suportado") : (isZh ? "仅限 ESP-IDF" : isDe ? "Nur ESP-IDF" : isFr ? "ESP-IDF uniquement" : isEs ? "Solo ESP-IDF" : isEn ? "ESP-IDF only" : "Só ESP-IDF"))],
|
||
].map(([rotulo, obter]) => (
|
||
<tr key={rotulo}>
|
||
<th scope="row" className="px-3 py-3 align-top font-medium text-muted">{rotulo}</th>
|
||
{topThree.map((rec) => (
|
||
<td key={rec.key} className="px-3 py-3 align-top">{obter(seriesData[rec.key])}</td>
|
||
))}
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<PlacasSugeridas chips={topThree.map((rec) => rec.key)} className="mt-10" />
|
||
|
||
{otherRecommendations.length > 0 && (
|
||
<div className="mt-10">
|
||
<h3 className="font-display text-xl font-semibold tracking-[-0.03em] text-ink">
|
||
{isZh ? "其他评估过的备选" : isDe ? "Weitere evaluierte Alternativen" : isFr ? "Autres alternatives évaluées" : isEs ? "Otras alternativas evaluadas" : isEn ? "Other evaluated alternatives" : "Outras alternativas avaliadas"}
|
||
</h3>
|
||
<ul className="mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||
{otherRecommendations.map((rec) => (
|
||
<li key={rec.key}>
|
||
<Link href={getLocalizedHref(`/series/${rec.key}`, currentLocale)} className="card card-interactive flex items-center justify-between gap-3 px-4 py-3.5">
|
||
<span className="font-display text-lg font-semibold tracking-[-0.03em] text-ink">{rec.key}</span>
|
||
<span className="text-sm text-muted">{rec.percentage}%</span>
|
||
</Link>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
)}
|
||
</section>
|
||
)}
|
||
|
||
{mode === "wizard" && showResults && recommendations.length === 0 && (
|
||
<section className="shell pb-6 pt-10">
|
||
<div className="card mx-auto max-w-2xl px-6 py-14 text-center">
|
||
<HelpCircle className="mx-auto h-10 w-10 text-gold" aria-hidden="true" />
|
||
<h2 className="mt-4 font-display text-2xl font-semibold text-ink">
|
||
{isZh ? "没有芯片满足全部要求" : isDe ? "Kein Chip erfüllt alle Anforderungen" : isFr ? "Aucune puce ne répond à toutes les exigences" : isEs ? "Ningún chip cumple con todos los requisitos" : isEn ? "No chip meets all requirements" : "Nenhum chip atende a todos os requisitos"}
|
||
</h2>
|
||
<p className="mx-auto mt-2 max-w-md text-sm text-muted">
|
||
{isZh ? "这个组合包含没有任何系列能同时满足的条件。请尝试放宽其中一个答案。" : isDe
|
||
? "Diese Kombination enthält Kriterien, die keine Serie gleichzeitig erfüllt. Lockern Sie eine der Antworten und versuchen Sie es erneut."
|
||
: isFr
|
||
? "Cette combinaison comporte des critères qu'aucune série ne satisfait simultanément. Assouplissez l'une des réponses et réessayez."
|
||
: isEs
|
||
? "Esta combinación tiene criterios que ninguna serie satisface simultáneamente. Pruebe relajando una de las respuestas."
|
||
: isEn
|
||
? "This combination has criteria that no series satisfies simultaneously. Try relaxing one of the answers."
|
||
: "Esta combinação tem critérios que nenhuma série cumpre ao mesmo tempo. Flexibilize uma das respostas e tente de novo."}
|
||
</p>
|
||
<div className="mt-6 flex flex-col justify-center gap-3 sm:flex-row">
|
||
<button type="button" onClick={() => { setShowResults(false); setShowSummary(true); }} className="btn btn-primary">
|
||
<Edit2 className="h-4 w-4" aria-hidden="true" />
|
||
{isZh ? "调整答案" : isDe ? "Antworten anpassen" : isFr ? "Ajuster les réponses" : isEs ? "Ajustar respuestas" : isEn ? "Adjust answers" : "Ajustar respostas"}
|
||
</button>
|
||
<button type="button" onClick={resetQuiz} className="btn btn-ghost">
|
||
<RotateCcw className="h-4 w-4" aria-hidden="true" />
|
||
{isEs ? "Reiniciar" : isEn ? "Restart" : "Recomeçar"}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
)}
|
||
|
||
{/* Filtro por recursos */}
|
||
{mode === "filter" && (
|
||
<section className="shell pb-6 pt-10" aria-labelledby="filtro-titulo">
|
||
<div className="panel p-5 sm:p-8">
|
||
<div className="flex flex-col justify-between gap-3 sm:flex-row sm:items-end">
|
||
<div className="max-w-xl">
|
||
<h2 id="filtro-titulo" className="section-title">
|
||
{isZh ? "勾选所需功能" : isDe ? "Wählen Sie erforderliche Funktionen" : isFr ? "Cochez ce qui est obligatoire" : isEs ? "Marque lo que es obligatorio" : isEn ? "Check required features" : "Marque o que é obrigatório"}
|
||
</h2>
|
||
<p className="mt-2 text-sm text-muted">
|
||
{isZh ? "只保留具备全部所选功能的系列。" : isDe
|
||
? "Es verbleiben nur Serien, die über alle ausgewählten Funktionen verfügen."
|
||
: isFr
|
||
? "Seules les séries disposant de toutes les fonctionnalités cochées sont conservées."
|
||
: isEs
|
||
? "Solo se conservan las series que cuentan con todas las funciones seleccionadas."
|
||
: isEn
|
||
? "Only series that have all selected features are kept."
|
||
: "Só ficam as séries que têm todos os recursos marcados."}
|
||
</p>
|
||
</div>
|
||
{filtrosAtivos > 0 && (
|
||
<button type="button" onClick={limparFiltros} className="inline-flex min-h-11 items-center gap-1.5 text-sm font-medium text-accent hover:text-accent-strong">
|
||
<RotateCcw className="h-4 w-4" aria-hidden="true" />
|
||
{isZh ? `清除 ${filtrosAtivos} 个筛选` : isDe
|
||
? `${filtrosAtivos} ${filtrosAtivos === 1 ? "Filter" : "Filter"} zurücksetzen`
|
||
: isFr
|
||
? `Effacer ${filtrosAtivos} ${filtrosAtivos === 1 ? "filtre" : "filtres"}`
|
||
: isEs
|
||
? `Limpiar ${filtrosAtivos} ${filtrosAtivos === 1 ? "filtro" : "filtros"}`
|
||
: isEn
|
||
? `Clear ${filtrosAtivos} ${filtrosAtivos === 1 ? "filter" : "filters"}`
|
||
: `Limpar ${filtrosAtivos} ${filtrosAtivos === 1 ? "filtro" : "filtros"}`}
|
||
</button>
|
||
)}
|
||
</div>
|
||
|
||
<div className="mt-6 flex flex-wrap gap-2" role="group" aria-label={isZh ? "功能" : isDe ? "Funktionen" : isFr ? "Fonctionnalités" : isEs ? "Recursos" : isEn ? "Features" : "Recursos"}>
|
||
{FILTROS.map(({ key, label }) => (
|
||
<button key={key} type="button" onClick={() => setFilters((prev) => ({ ...prev, [key]: !prev[key] }))} aria-pressed={filters[key]} className="chip-btn">
|
||
{filters[key] && <Check className="h-4 w-4" aria-hidden="true" />}
|
||
{label}
|
||
</button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<h3 role="status" aria-live="polite" className="mt-8 text-base font-semibold text-ink">
|
||
{isZh ? `${Object.keys(seriesData).length} 个系列中有 ${filteredChips.length} 个匹配` : isDe
|
||
? `${filteredChips.length} von ${Object.keys(seriesData).length} Serien passen`
|
||
: isFr
|
||
? `${filteredChips.length} sur ${Object.keys(seriesData).length} séries compatibles`
|
||
: isEs
|
||
? `${filteredChips.length} de ${Object.keys(seriesData).length} series compatibles`
|
||
: isEn
|
||
? `${filteredChips.length} of ${Object.keys(seriesData).length} series match`
|
||
: `${filteredChips.length} de ${Object.keys(seriesData).length} séries compatíveis`}
|
||
</h3>
|
||
|
||
{filteredChips.length > 0 ? (
|
||
<div className="mt-4 grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||
{filteredChips.map(([seriesKey, serie]) => (
|
||
<Link key={seriesKey} href={getLocalizedHref(`/series/${seriesKey}`, currentLocale)} className="card card-interactive group flex flex-col p-5 sm:p-6">
|
||
<h4 className="font-display text-2xl font-semibold tracking-[-0.035em] text-ink">{seriesKey}</h4>
|
||
<p className="mt-1 line-clamp-2 min-h-[2.9rem] text-sm text-muted">{serie.descricao}</p>
|
||
<dl className="mt-4 divide-y divide-line border-y border-line text-sm">
|
||
{[
|
||
["Wi-Fi", serie.wifi],
|
||
["Matter / Thread", (serie.matter === "Sim" || serie.matter === "Yes" || serie.matter === "Sí" || serie.matter === "Oui" || (serie.matter === "Ja" || serie.matter === "是")) ? (isZh ? "是" : isDe ? "Ja" : isFr ? "Oui" : isEs ? "Sí" : isEn ? "Yes" : "Sim") : (isZh ? "否" : isDe ? "Nein" : isFr ? "Non" : isEs || isEn ? "No" : "Não")],
|
||
["Clock", serie.frequencia],
|
||
["GPIO", isZh ? `${serie.gpio} 个引脚` : isDe ? `${serie.gpio} Pins` : isFr ? `${serie.gpio} broches` : isEs ? `${serie.gpio} pines` : isEn ? `${serie.gpio} pins` : `${serie.gpio} pinos`],
|
||
["PSRAM", (serie.psram_externa && serie.psram_externa !== "Não" && serie.psram_externa !== "No" && serie.psram_externa !== "Non" && (serie.psram_externa !== "Nein" && serie.psram_externa !== "否")) ? serie.psram_externa : (isZh ? "否" : isDe ? "Nein" : isFr ? "Non" : isEs || isEn ? "No" : "Não")],
|
||
].map(([rotulo, valor]) => (
|
||
<div key={rotulo} className="flex items-baseline justify-between gap-4 py-2">
|
||
<dt className="text-muted">{rotulo}</dt>
|
||
<dd className="truncate text-right font-medium text-ink">{valor}</dd>
|
||
</div>
|
||
))}
|
||
</dl>
|
||
<span className="mt-4 inline-flex items-center gap-1 text-sm font-medium text-accent">
|
||
{isZh ? "打开数据手册" : isDe ? "Datenblatt öffnen" : isFr ? "Ouvrir la fiche" : isEs ? "Abrir ficha" : isEn ? "Open datasheet" : "Abrir ficha"}
|
||
<ArrowUpRight className="h-4 w-4 transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5" aria-hidden="true" />
|
||
</span>
|
||
</Link>
|
||
))}
|
||
</div>
|
||
) : (
|
||
<div className="card mt-4 px-6 py-14 text-center">
|
||
<HelpCircle className="mx-auto h-10 w-10 text-gold" aria-hidden="true" />
|
||
<h4 className="mt-4 font-display text-xl font-semibold text-ink">
|
||
{isZh ? "没有系列满足全部筛选条件" : isDe ? "Keine Serie erfüllt alle Filter" : isFr ? "Aucune série ne répond à tous les filtres" : isEs ? "Ninguna serie cumple con todos los filtros" : isEn ? "No series matches all filters" : "Nenhuma série atende a todos os filtros"}
|
||
</h4>
|
||
<p className="mx-auto mt-2 max-w-md text-sm text-muted">
|
||
{isZh ? "请取消一些限制较多的功能,例如同时要求 5 GHz Wi-Fi 和以太网 MAC。" : isDe
|
||
? "Deaktivieren Sie restriktivere Funktionen wie 5-GHz-Wi-Fi zusammen mit Ethernet-MAC."
|
||
: isFr
|
||
? "Décochez les fonctionnalités les plus restrictives, comme le Wi-Fi 5 GHz combiné à l'Ethernet MAC."
|
||
: isEs
|
||
? "Desmarque las funciones más restrictivas, como Wi-Fi de 5 GHz junto con Ethernet MAC."
|
||
: isEn
|
||
? "Uncheck more restrictive features, like 5 GHz Wi-Fi together with Ethernet MAC."
|
||
: "Desmarque os recursos mais restritivos, como Wi-Fi 5 GHz junto com Ethernet MAC."}
|
||
</p>
|
||
<button type="button" onClick={limparFiltros} className="btn btn-primary mt-6">
|
||
{isEs ? "Limpiar filtros" : isEn ? "Clear filters" : "Limpar filtros"}
|
||
</button>
|
||
</div>
|
||
)}
|
||
{filteredChips.length > 0 && <PlacasSugeridas chips={filteredChips.map(([chave]) => chave)} className="mt-6" />}
|
||
</section>
|
||
)}
|
||
|
||
<section className="shell section" aria-labelledby="proximos-titulo">
|
||
<h2 id="proximos-titulo" className="section-title">
|
||
{isZh ? "后续步骤" : isDe ? "Nächste Schritte" : isFr ? "Prochaines étapes" : isEs ? "Próximos pasos" : isEn ? "Next steps" : "Próximos passos"}
|
||
</h2>
|
||
<div className="mt-8 grid gap-4 md:grid-cols-3">
|
||
{[
|
||
{
|
||
href: "/catalogo",
|
||
icon: ShoppingBag,
|
||
titulo: isZh ? "开发板目录" : isDe ? "Board-Katalog" : isFr ? "Catalogue de cartes" : isEs ? "Catálogo de placas" : isEn ? "Board catalog" : "Catálogo de placas",
|
||
texto: isZh ? "真实的 DevKit 与模组,含引脚和官方商店链接。" : isDe
|
||
? "Echte DevKits und Module mit Pinbelegung und Link zum offiziellen Shop."
|
||
: isFr
|
||
? "Vrais DevKits et modules avec brochage et lien vers la boutique officielle."
|
||
: isEs
|
||
? "DevKits y módulos reales, con patillaje y enlace a la tienda oficial."
|
||
: isEn
|
||
? "Real DevKits and modules, with pinout and official store links."
|
||
: "DevKits e módulos reais, com pinagem e link para a loja."
|
||
},
|
||
{
|
||
href: "/comparacao",
|
||
icon: SlidersHorizontal,
|
||
titulo: isZh ? "并排对比" : isDe ? "Vergleich Seite an Seite" : isFr ? "Comparateur côte à côte" : isEs ? "Comparador lado a lado" : isEn ? "Side-by-side comparison" : "Comparador lado a lado",
|
||
texto: isZh ? "在同一张表中查看频率、GPIO、ADC/DAC、功耗和安全。" : isDe
|
||
? "Taktfrequenz, GPIOs, ADC/DAC, Stromverbrauch und Sicherheit in einer Tabelle."
|
||
: isFr
|
||
? "Fréquence, GPIO, ADC/DAC, consommation et sécurité dans un tableau."
|
||
: isEs
|
||
? "Frecuencia, GPIOs, ADC/DAC, consumo y seguridad en una tabla."
|
||
: isEn
|
||
? "Frequency, GPIOs, ADC/DAC, power consumption, and security in one table."
|
||
: "Frequência, GPIOs, ADC/DAC, consumo e segurança em uma tabela."
|
||
},
|
||
{
|
||
href: "/glossario",
|
||
icon: BookOpen,
|
||
titulo: isZh ? "技术术语表" : isDe ? "Technisches Glossar" : isFr ? "Glossaire technique" : isEs ? "Glosario técnico" : isEn ? "Technical glossary" : "Glossário técnico",
|
||
texto: isZh ? "对 ULP、RTC SRAM、JTAG 或 Matter 有疑问?查看定义。" : isDe
|
||
? "Fragen zu ULP, RTC-SRAM, JTAG oder Matter? Schlagen Sie die Definitionen nach."
|
||
: isFr
|
||
? "Des doutes sur l'ULP, la SRAM RTC, le JTAG ou Matter ? Consultez les définitions."
|
||
: isEs
|
||
? "¿Dudas sobre ULP, SRAM RTC, JTAG o Matter? Consulte las definiciones."
|
||
: isEn
|
||
? "Questions about ULP, RTC SRAM, JTAG or Matter? Check definitions."
|
||
: "Dúvida sobre ULP, SRAM RTC, JTAG ou Matter? Veja as definições."
|
||
},
|
||
].map(({ href, icon: Icon, titulo, texto }) => (
|
||
<Link key={href} href={getLocalizedHref(href, currentLocale)} className="card card-interactive group flex flex-col p-5 sm:p-6">
|
||
<span className="grid h-10 w-10 place-items-center rounded-full bg-accent-soft text-accent">
|
||
<Icon className="h-5 w-5" aria-hidden="true" />
|
||
</span>
|
||
<h3 className="mt-4 font-display text-xl font-semibold tracking-[-0.03em] text-ink">{titulo}</h3>
|
||
<p className="mt-2 flex-1 text-sm leading-relaxed text-muted">{texto}</p>
|
||
<span className="mt-4 inline-flex items-center gap-1 text-sm font-medium text-accent">
|
||
{isZh ? "打开" : isDe ? "Öffnen" : isFr ? "Ouvrir" : isEs ? "Abrir" : isEn ? "Open" : "Abrir"}
|
||
<ArrowRight className="h-4 w-4 transition-transform group-hover:translate-x-0.5" aria-hidden="true" />
|
||
</span>
|
||
</Link>
|
||
))}
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<Footer />
|
||
</div>
|
||
);
|
||
}
|