Skip to content

Deteccion Match

🎯 Objetivo

Crear un sistema de matching que proporcione feedback visual instantáneo al usuario, combinando preconsulta, Cloud Functions y StreamBuilder para garantizar una experiencia fluida y confiable.

🏗️ ARQUITECTURA DEL SISTEMA

Componentes Principales:

1. Preconsulta (Paso 1)

Ubicación: MatchingProfilesController
Función: Verificar si el usuario actual ya recibió like
Trigger: Al cargar cada perfil
Almacenamiento: hasLikedMeMap<String, bool>

2. Cloud Function (Paso 2)

Ubicación: functions/main.py
Función: Detectar matches automáticamente
Trigger: Cuando se crea un documento en /users/{userId}/likesGiven/{likedUserId}
Procesamiento: Verificar reciprocidad y crear match

3. StreamBuilder (Paso 3)

Ubicación: MatchingProfilesScreen
Función: Detectar matches que no se anticiparon
Trigger: Cambios en colección /matches
Resultado: Animación retroactiva

🔄 FLUJO DE DATOS COMPLETO

Fase 1: Carga de Perfil

Usuario abre pantalla de matching
MatchingProfilesController.loadProfiles()
Para cada perfil: checkIfUserLikedMe(userId)
Consulta: /users/{otherUserId}/likesGiven/{currentUserId}
Resultado guardado en: hasLikedMeMap[userId] = true/false

Fase 2: Usuario Da Like

Usuario presiona botón like
MatchingProfilesController.onLike()
Verificar: hasLikedMe = getHasLikedMe(likedUserId)
Si hasLikedMe == true:
→ Mostrar animación instantánea
→ Cloud Function en paralelo
Si hasLikedMe == false:
→ Solo Cloud Function

Fase 3: Cloud Function

Documento creado en: /users/{userId}/likesGiven/{likedUserId}
Trigger automático: detect_match()
Verificar: /users/{likedUserId}/likesGiven/{userId}
Si existe reciprocidad:
→ Crear match en /matches/{matchId}
→ Log: "¡MATCH detectado!"
Si no existe:
→ Log: "No hay match aún"

Fase 4: StreamBuilder

Cambio detectado en: /matches
StreamBuilder procesa nuevo documento
Verificar: isNewMatch(matchId)
Si es match nuevo:
→ Obtener datos del otro usuario
→ Mostrar animación retroactiva

ESTRUCTURA DE ARCHIVOS

lib/
├── features/
│ └── matching/
│ ├── controllers/
│ │ └── matching_profiles_controller.dart
│ │ ├── hasLikedMeMap (Map<String, bool>)
│ │ ├── checkIfUserLikedMe() (Future<bool>)
│ │ ├── getHasLikedMe() (bool)
│ │ ├── matchesStream (Stream<QuerySnapshot>)
│ │ ├── isNewMatch() (bool)
│ │ └── showRetroactiveMatchAnimation()
│ └── presentation/
│ └── screens/
│ └── matchingprofilescreen.dart
│ ├── StreamBuilder<QuerySnapshot>
│ └── _showRetroactiveMatchAnimation()

functions/
└── main.py
└── detect_match() (Cloud Function)

ESTRUCTURA DE FIRESTORE

/users/
├── {userId}/
│ ├── likesGiven/
│ │ └── {likedUserId}/
│ │ ├── eventId: string
│ │ └── timestamp: timestamp
│ └── likesReceived/
│ └── {likerUserId}/
│ ├── eventId: string
│ └── timestamp: timestamp

/matches/
└── {matchId}/
├── users: [userId1, userId2]
├── eventId: string
├── createdAt: timestamp
└── lastEventId: string

⚡ CASOS DE USO

Caso 1: Match Instantáneo

Precondición:
A ya le dio like a B
Acción: B da like a A

Resultado: Animación inmediata (0ms)

Caso 2: Match Posterior

Precondición: A no le dio like a B
Acción 1: A da like a B → No animación
Acción 2: B da like a A → Animación para B


Caso 3: Fallback

Precondición: Preconsulta falla
Acción: A y B se dan like
Resultado: StreamBuilder captura y muestra animación
funciones

📊 MÉTRICAS DE PERFORMANCE

Tiempos Esperados:

Preconsulta: 50-150ms
Animación instantánea: 0ms
Cloud Function: 100-300ms
StreamBuilder: 50-200ms

Casos de Éxito:

Match instantáneo: 95% de casos
Match posterior: 5% de casos
Fallback: <1% de casos

��️ MANEJO DE ERRORES

Preconsulta falla:

hasLikedMeMap[userId] = false (por defecto)
StreamBuilder captura el match

Cloud Function falla:

Logs detallados para debugging
No re-lanza excepciones

StreamBuilder falla:

No afecta funcionalidad básica
Match se crea igual en Firestore
Want to print your doc?
This is not the way.
Try clicking the ··· in the right corner or using a keyboard shortcut (
CtrlP
) instead.