feat: update ESLint and TypeScript configurations across frontend and backend; enhance component structure and improve data handling in various modules
This commit is contained in:
@@ -123,7 +123,7 @@ function detectarSistemaOperacional(): {
|
||||
sistemaOperacional: 'Desconhecido',
|
||||
osVersion: '',
|
||||
arquitetura: '',
|
||||
plataforma: '',
|
||||
plataforma: ''
|
||||
};
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ function detectarSistemaOperacional(): {
|
||||
'10.0': '10/11',
|
||||
'6.3': '8.1',
|
||||
'6.2': '8',
|
||||
'6.1': '7',
|
||||
'6.1': '7'
|
||||
};
|
||||
osVersion = versions[version] || version;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ function detectarTipoDispositivo(): {
|
||||
deviceType: 'Desconhecido',
|
||||
isMobile: false,
|
||||
isTablet: false,
|
||||
isDesktop: true,
|
||||
isDesktop: true
|
||||
};
|
||||
}
|
||||
|
||||
@@ -232,7 +232,8 @@ async function obterInformacoesConexao(): Promise<string> {
|
||||
return 'Desconhecido';
|
||||
}
|
||||
|
||||
const connection = (navigator as unknown as { connection?: { effectiveType?: string } }).connection;
|
||||
const connection = (navigator as unknown as { connection?: { effectiveType?: string } })
|
||||
.connection;
|
||||
if (connection?.effectiveType) {
|
||||
return connection.effectiveType;
|
||||
}
|
||||
@@ -260,12 +261,7 @@ function obterInformacoesMemoria(): string {
|
||||
* Calcula distância entre duas coordenadas (fórmula de Haversine)
|
||||
* Retorna distância em metros
|
||||
*/
|
||||
function calcularDistancia(
|
||||
lat1: number,
|
||||
lon1: number,
|
||||
lat2: number,
|
||||
lon2: number
|
||||
): number {
|
||||
function calcularDistancia(lat1: number, lon1: number, lat2: number, lon2: number): number {
|
||||
const R = 6371000; // Raio da Terra em metros
|
||||
const dLat = ((lat2 - lat1) * Math.PI) / 180;
|
||||
const dLon = ((lon2 - lon1) * Math.PI) / 180;
|
||||
@@ -287,7 +283,7 @@ function obterTimezonePorCoordenadas(latitude: number, longitude: number): strin
|
||||
if (longitude >= -45 && longitude <= -30 && latitude >= -10 && latitude <= 5) {
|
||||
return 'America/Recife'; // UTC-3
|
||||
}
|
||||
|
||||
|
||||
// Fallback: usar timezone do sistema
|
||||
try {
|
||||
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
@@ -358,7 +354,7 @@ async function capturarLocalizacaoUnica(
|
||||
// Calcular confiabilidade: cada sinal adiciona pontos
|
||||
let pontos = 0;
|
||||
const maxPontos = 7;
|
||||
|
||||
|
||||
if (sinaisGPSReal.temAltitude) pontos += 1;
|
||||
if (sinaisGPSReal.temAltitudeAccuracy) pontos += 1;
|
||||
if (sinaisGPSReal.temHeading) pontos += 0.5;
|
||||
@@ -412,7 +408,11 @@ async function obterLocalizacaoMultipla(): Promise<{
|
||||
motivoSuspeita?: string;
|
||||
}> {
|
||||
if (typeof navigator === 'undefined' || !navigator.geolocation) {
|
||||
return { confiabilidade: 0, suspeitaSpoofing: true, motivoSuspeita: 'Geolocalização não suportada' };
|
||||
return {
|
||||
confiabilidade: 0,
|
||||
suspeitaSpoofing: true,
|
||||
motivoSuspeita: 'Geolocalização não suportada'
|
||||
};
|
||||
}
|
||||
|
||||
// Capturar 3 leituras com intervalo de 2 segundos entre elas
|
||||
@@ -426,7 +426,7 @@ async function obterLocalizacaoMultipla(): Promise<{
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const leitura = await capturarLocalizacaoUnica(true, 8000);
|
||||
|
||||
|
||||
if (leitura.latitude && leitura.longitude && leitura.confiabilidade > 0) {
|
||||
leituras.push({
|
||||
lat: leitura.latitude,
|
||||
@@ -436,7 +436,7 @@ async function obterLocalizacaoMultipla(): Promise<{
|
||||
confiabilidade: leitura.confiabilidade
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Aguardar 2 segundos entre leituras (exceto na última)
|
||||
if (i < 2) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
@@ -444,7 +444,11 @@ async function obterLocalizacaoMultipla(): Promise<{
|
||||
}
|
||||
|
||||
if (leituras.length === 0) {
|
||||
return { confiabilidade: 0, suspeitaSpoofing: true, motivoSuspeita: 'Não foi possível obter localização' };
|
||||
return {
|
||||
confiabilidade: 0,
|
||||
suspeitaSpoofing: true,
|
||||
motivoSuspeita: 'Não foi possível obter localização'
|
||||
};
|
||||
}
|
||||
|
||||
// Se tivermos menos de 2 leituras, usar única leitura com baixa confiança
|
||||
@@ -546,7 +550,7 @@ export async function obterLocalizacaoRapida(): Promise<{
|
||||
try {
|
||||
// Uma única leitura rápida com timeout curto
|
||||
const leitura = await capturarLocalizacaoUnica(true, 3000); // 3 segundos máximo
|
||||
|
||||
|
||||
if (!leitura.latitude || !leitura.longitude || leitura.confiabilidade === 0) {
|
||||
return {};
|
||||
}
|
||||
@@ -566,12 +570,12 @@ export async function obterLocalizacaoRapida(): Promise<{
|
||||
}
|
||||
}
|
||||
);
|
||||
const geocodeTimeout = new Promise<Response>((_, reject) =>
|
||||
const geocodeTimeout = new Promise<Response>((_, reject) =>
|
||||
setTimeout(() => reject(new Error('Timeout')), 2000)
|
||||
);
|
||||
|
||||
|
||||
const response = await Promise.race([geocodePromise, geocodeTimeout]);
|
||||
|
||||
|
||||
if (response.ok) {
|
||||
const data = (await response.json()) as {
|
||||
address?: {
|
||||
@@ -649,7 +653,18 @@ export async function obterLocalizacao(): Promise<{
|
||||
};
|
||||
}
|
||||
|
||||
const { latitude, longitude, precisao, altitude, altitudeAccuracy, heading, speed, confiabilidade, suspeitaSpoofing, motivoSuspeita } = localizacaoMultipla;
|
||||
const {
|
||||
latitude,
|
||||
longitude,
|
||||
precisao,
|
||||
altitude,
|
||||
altitudeAccuracy,
|
||||
heading,
|
||||
speed,
|
||||
confiabilidade,
|
||||
suspeitaSpoofing,
|
||||
motivoSuspeita
|
||||
} = localizacaoMultipla;
|
||||
|
||||
// Tentar obter endereço via reverse geocoding
|
||||
let endereco = '';
|
||||
@@ -695,9 +710,13 @@ export async function obterLocalizacao(): Promise<{
|
||||
if (typeof navigator !== 'undefined') {
|
||||
const timezoneAtual = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
const timezoneEsperado = obterTimezonePorCoordenadas(latitude, longitude);
|
||||
|
||||
|
||||
// Se timezone é muito diferente, pode ser suspeito
|
||||
if (timezoneAtual !== timezoneEsperado && timezoneAtual !== 'America/Recife' && timezoneEsperado !== 'America/Recife') {
|
||||
if (
|
||||
timezoneAtual !== timezoneEsperado &&
|
||||
timezoneAtual !== 'America/Recife' &&
|
||||
timezoneEsperado !== 'America/Recife'
|
||||
) {
|
||||
console.warn(`Timezone inconsistente: esperado ${timezoneEsperado}, atual ${timezoneAtual}`);
|
||||
}
|
||||
}
|
||||
@@ -748,13 +767,19 @@ export async function obterIPPublico(): Promise<string | undefined> {
|
||||
* Solicita permissão para acesso aos sensores de movimento (iOS 13+)
|
||||
*/
|
||||
async function solicitarPermissaoSensor(): Promise<PermissionState> {
|
||||
if (typeof DeviceMotionEvent === 'undefined' || typeof (DeviceMotionEvent as { requestPermission?: () => Promise<PermissionState> }).requestPermission !== 'function') {
|
||||
if (
|
||||
typeof DeviceMotionEvent === 'undefined' ||
|
||||
typeof (DeviceMotionEvent as { requestPermission?: () => Promise<PermissionState> })
|
||||
.requestPermission !== 'function'
|
||||
) {
|
||||
// Permissão não necessária ou já concedida (navegadores modernos)
|
||||
return 'granted';
|
||||
}
|
||||
|
||||
try {
|
||||
const requestPermission = (DeviceMotionEvent as { requestPermission: () => Promise<PermissionState> }).requestPermission;
|
||||
const requestPermission = (
|
||||
DeviceMotionEvent as { requestPermission: () => Promise<PermissionState> }
|
||||
).requestPermission;
|
||||
const resultado = await requestPermission();
|
||||
return resultado;
|
||||
} catch (error) {
|
||||
@@ -783,7 +808,7 @@ async function obterDadosAcelerometro(duracaoMs: number = 5000): Promise<{
|
||||
|
||||
// Solicitar permissão (especialmente necessário no iOS 13+)
|
||||
const permissao = await solicitarPermissaoSensor();
|
||||
|
||||
|
||||
if (permissao === 'denied') {
|
||||
return {
|
||||
sensorDisponivel: true,
|
||||
@@ -793,36 +818,44 @@ async function obterDadosAcelerometro(duracaoMs: number = 5000): Promise<{
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const leiturasAcelerometro: Array<{ x: number; y: number; z: number; timestamp: number }> = [];
|
||||
const leiturasGiroscopio: Array<{ alpha: number; beta: number; gamma: number; timestamp: number }> = [];
|
||||
|
||||
const leiturasGiroscopio: Array<{
|
||||
alpha: number;
|
||||
beta: number;
|
||||
gamma: number;
|
||||
timestamp: number;
|
||||
}> = [];
|
||||
|
||||
const timeoutId = setTimeout(() => {
|
||||
window.removeEventListener('devicemotion', handleDeviceMotion);
|
||||
window.removeEventListener('deviceorientation', handleDeviceOrientation);
|
||||
|
||||
|
||||
// Processar dados de acelerômetro
|
||||
let acelerometro: DadosAcelerometro | undefined;
|
||||
if (leiturasAcelerometro.length > 0) {
|
||||
const ultimaLeitura = leiturasAcelerometro[leiturasAcelerometro.length - 1]!;
|
||||
|
||||
|
||||
// Calcular magnitude média
|
||||
const magnitudes = leiturasAcelerometro.map(l =>
|
||||
const magnitudes = leiturasAcelerometro.map((l) =>
|
||||
Math.sqrt(l.x * l.x + l.y * l.y + l.z * l.z)
|
||||
);
|
||||
const magnitude = magnitudes.reduce((sum, m) => sum + m, 0) / magnitudes.length;
|
||||
|
||||
|
||||
// Calcular variância para detectar movimento
|
||||
const mediaX = leiturasAcelerometro.reduce((sum, l) => sum + l.x, 0) / leiturasAcelerometro.length;
|
||||
const mediaY = leiturasAcelerometro.reduce((sum, l) => sum + l.y, 0) / leiturasAcelerometro.length;
|
||||
const mediaZ = leiturasAcelerometro.reduce((sum, l) => sum + l.z, 0) / leiturasAcelerometro.length;
|
||||
|
||||
const variacoes = leiturasAcelerometro.map(l =>
|
||||
Math.pow(l.x - mediaX, 2) + Math.pow(l.y - mediaY, 2) + Math.pow(l.z - mediaZ, 2)
|
||||
const mediaX =
|
||||
leiturasAcelerometro.reduce((sum, l) => sum + l.x, 0) / leiturasAcelerometro.length;
|
||||
const mediaY =
|
||||
leiturasAcelerometro.reduce((sum, l) => sum + l.y, 0) / leiturasAcelerometro.length;
|
||||
const mediaZ =
|
||||
leiturasAcelerometro.reduce((sum, l) => sum + l.z, 0) / leiturasAcelerometro.length;
|
||||
|
||||
const variacoes = leiturasAcelerometro.map(
|
||||
(l) => Math.pow(l.x - mediaX, 2) + Math.pow(l.y - mediaY, 2) + Math.pow(l.z - mediaZ, 2)
|
||||
);
|
||||
const variacao = variacoes.reduce((sum, v) => sum + v, 0) / variacoes.length;
|
||||
|
||||
|
||||
// Detectar movimento: se variância > 0.01, há movimento
|
||||
const movimentoDetectado = variacao > 0.01;
|
||||
|
||||
|
||||
acelerometro = {
|
||||
x: ultimaLeitura.x,
|
||||
y: ultimaLeitura.y,
|
||||
@@ -833,7 +866,7 @@ async function obterDadosAcelerometro(duracaoMs: number = 5000): Promise<{
|
||||
timestamp: ultimaLeitura.timestamp
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Processar dados de giroscópio
|
||||
let giroscopio: DadosGiroscopio | undefined;
|
||||
if (leiturasGiroscopio.length > 0) {
|
||||
@@ -844,7 +877,7 @@ async function obterDadosAcelerometro(duracaoMs: number = 5000): Promise<{
|
||||
gamma: ultimaLeitura.gamma || 0
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
resolve({
|
||||
acelerometro,
|
||||
giroscopio,
|
||||
@@ -852,7 +885,7 @@ async function obterDadosAcelerometro(duracaoMs: number = 5000): Promise<{
|
||||
permissaoNegada: false
|
||||
});
|
||||
}, duracaoMs);
|
||||
|
||||
|
||||
function handleDeviceMotion(event: DeviceMotionEvent) {
|
||||
if (event.accelerationIncludingGravity) {
|
||||
const acc = event.accelerationIncludingGravity;
|
||||
@@ -866,7 +899,7 @@ async function obterDadosAcelerometro(duracaoMs: number = 5000): Promise<{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleDeviceOrientation(event: DeviceOrientationEvent) {
|
||||
if (event.alpha !== null && event.beta !== null && event.gamma !== null) {
|
||||
leiturasGiroscopio.push({
|
||||
@@ -877,7 +910,7 @@ async function obterDadosAcelerometro(duracaoMs: number = 5000): Promise<{
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
window.addEventListener('devicemotion', handleDeviceMotion);
|
||||
window.addEventListener('deviceorientation', handleDeviceOrientation);
|
||||
});
|
||||
@@ -922,14 +955,15 @@ export async function obterInformacoesDispositivo(): Promise<InformacoesDisposit
|
||||
informacoes.coresTela = tela.coresTela;
|
||||
|
||||
// Informações de conexão, memória e localização (assíncronas)
|
||||
const [connectionType, memoryInfo, ipPublico, ipLocal, localizacao, dadosSensores] = await Promise.all([
|
||||
obterInformacoesConexao(),
|
||||
Promise.resolve(obterInformacoesMemoria()),
|
||||
obterIPPublico(),
|
||||
getLocalIP(),
|
||||
obterLocalizacao(),
|
||||
obterDadosAcelerometro(5000), // Coletar dados por 5 segundos
|
||||
]);
|
||||
const [connectionType, memoryInfo, ipPublico, ipLocal, localizacao, dadosSensores] =
|
||||
await Promise.all([
|
||||
obterInformacoesConexao(),
|
||||
Promise.resolve(obterInformacoesMemoria()),
|
||||
obterIPPublico(),
|
||||
getLocalIP(),
|
||||
obterLocalizacao(),
|
||||
obterDadosAcelerometro(5000) // Coletar dados por 5 segundos
|
||||
]);
|
||||
|
||||
informacoes.connectionType = connectionType;
|
||||
informacoes.memoryInfo = memoryInfo;
|
||||
@@ -961,4 +995,3 @@ export async function obterInformacoesDispositivo(): Promise<InformacoesDisposit
|
||||
|
||||
return informacoes;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user