Let me continue with the matching algorithm code: matching-algorithm application/vnd.ant.code Personality-Based Matching Algorithm update // services/matchingService.js const User = require('../models/User'); const Match = require('../models/Match'); const MatchRequest = require('../models/MatchRequest'); const { calculateCompatibilityScore } = require('./compatibilityService'); /** * Find potential matches for a user * @param {String} userId - ID of the user to find matches for * @param {Number} limit - Maximum number of potential matches to return * @returns {Array} Array of potential matches with compatibility scores */ async function findPotentialMatches(userId, limit = 20) { try { // Get user's profile and preferences const user = await User.findById(userId); if (!user) { throw new Error('User not found'); } // Get user's existing matches and match requests to exclude them const existingMatches = await Match.find({ $or: [{ user1: userId }, { user2: userId }], status: { $in: ['active', 'paused'] } }); const sentRequests = await MatchRequest.find({ sender: userId, status: 'pending' }); const receivedRequests = await MatchRequest.find({ receiver: userId, status: 'pending' }); // Create list of users to exclude from potential matches const excludeUserIds = [ userId, // Exclude self ...existingMatches.map(match => match.user1.toString() === userId.toString() ? match.user2.toString() : match.user1.toString() ), ...sentRequests.map(req => req.receiver.toString()), ...receivedRequests.map(req => req.sender.toString()) ]; // Build query for finding potential matches const matchQuery = { _id: { $nin: excludeUserIds }, isActive: true, isVerified: true, // Filter by gender preferences gender: { $in: user.lookingFor }, lookingFor: { $in: [user.gender] } }; // Add age range filter if specified if (user.ageRangeMin && user.ageRangeMax) { const minDate = new Date(); minDate.setFullYear(minDate.getFullYear() - user.ageRangeMax); const maxDate = new Date(); maxDate.setFullYear(maxDate.getFullYear() - user.ageRangeMin); matchQuery.birthdate = { $gte: minDate, $lte: maxDate }; } // Find potential matches based on initial criteria const potentialMatches = await User.find(matchQuery) .select('_id displayName birthdate gender interests values personalityTraits communicationStyle location lastActive') .limit(limit * 2); // Get extra matches to filter down after scoring // Calculate compatibility scores for each potential match const scoredMatches = await Promise.all( potentialMatches.map(async match => { const compatibilityScore = await calculateCompatibilityScore(user, match); return { user: match, score: compatibilityScore, distanceKm: calculateDistance( user.location.coordinates, match.location.coordinates ), lastActive: match.lastActive }; }) ); // Sort by compatibility score and limit results return scoredMatches .sort((a, b) => b.score - a.score) .slice(0, limit); } catch (error) { console.error('Error finding potential matches:', error); throw error; } } /** * Calculate compatibility score between two users * This is imported from compatibilityService.js in the actual implementation * but included here for reference * * @param {Object} user1 - First user * @param {Object} user2 - Second user * @returns {Number} Compatibility score (0-100) */ function calculateCompatibilityScore(user1, user2) { // Initialize score components let personalityScore = 0; let interestsScore = 0; let valuesScore = 0; let communicationScore = 0; // 1. Personality traits comparison (40% of total score) // Compare each personality trait dimension const personalityTraits = [ 'openness', 'conscientiousness', 'extraversion', 'agreeableness', 'neuroticism' ]; let personalityDiffSum = 0; for (const trait of personalityTraits) { if (user1.personalityTraits.has(trait) && user2.personalityTraits.has(trait)) { // Calculate difference (0-1 scale) const diff = Math.abs( user1.personalityTraits.get(trait) - user2.personalityTraits.get(trait) ); personalityDiffSum += diff; } } // Convert difference to similarity score (0-40) personalityScore = 40 * (1 - (personalityDiffSum / personalityTraits.length)); // 2. Shared interests comparison (25% of total score) const user1Interests = new Set(user1.interests); const user2Interests = new Set(user2.interests); // Count shared interests let sharedInterests = 0; for (const interest of user1Interests) { if (user2Interests.has(interest)) { sharedInterests++; } } // Calculate interest score based on overlap percentage const totalInterests = Math.max(1, user1Interests.size + user2Interests.size - sharedInterests); interestsScore = 25 * (sharedInterests / totalInterests); // 3. Shared values comparison (25% of total score) const user1Values = new Set(user1.values); const user2Values = new Set(user2.values); // Count shared values let sharedValues = 0; for (const value of user1Values) { if (user2Values.has(value)) { sharedValues++; } } // Calculate values score based on overlap percentage const totalValues = Math.max(1, user1Values.size + user2Values.size - sharedValues); valuesScore = 25 * (sharedValues / totalValues); // 4. Communication style compatibility (10% of total score) // Predefined compatibility matrix for communication styles const communicationCompatibility = { 'direct': { 'direct': 1.0, 'thoughtful': 0.7, 'humorous': 0.8, 'deep': 0.6, 'casual': 0.7 }, 'thoughtful': { 'direct': 0.7, 'thoughtful': 1.0, 'humorous': 0.6, 'deep': 0.9, 'casual': 0.5 }, 'humorous': { 'direct': 0.8, 'thoughtful': 0.6, 'humorous': 1.0, 'deep': 0.7, 'casual': 0.9 }, 'deep': { 'direct': 0.6, 'thoughtful': 0.9, 'humorous': 0.7, 'deep': 1.0, 'casual': 0.5 }, 'casual': { 'direct': 0.7, 'thoughtful': 0.5, 'humorous': 0.9, 'deep': 0.5, 'casual': 1.0 } }; // Calculate communication style compatibility if (user1.communicationStyle && user2.communicationStyle) { const compatibilityValue = communicationCompatibility[user1.communicationStyle][user2.communicationStyle] || 0.5; communicationScore = 10 * compatibilityValue; } else { // Default if communication style not specified communicationScore = 5; } // Calculate total score (0-100) const totalScore = personalityScore + interestsScore + valuesScore + communicationScore; return Math.round(totalScore); } /** * Calculate distance between two points in kilometers * Using Haversine formula * * @param {Array} coords1 - [longitude, latitude] of first point * @param {Array} coords2 - [longitude, latitude] of second point * @returns {Number} Distance in kilometers */ function calculateDistance(coords1, coords2) { // Earth's radius in kilometers const R = 6371; const [lon1, lat1] = coords1; const [lon2, lat2] = coords2; // Convert to radians const dLat = (lat2 - lat1) * Math.PI / 180; const dLon = (lon2 - lon1) * Math.PI / 180; const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon/2) * Math.sin(dLon/2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); const distance = R * c; return distance; } /** * Send a match request to another user * * @param {String} senderId - ID of the sending user * @param {String} receiverId - ID of the receiving user * @returns {Object} Created match request */ async function sendMatchRequest(senderId, receiverId) { try { // Check if users exist const [sender, receiver] = await Promise.all([ User.findById(senderId), User.findById(receiverId) ]); if (!sender || !receiver) { throw new Error('User not found'); } // Check if there's already a match between these users const existingMatch = await Match.findOne({ $or: [ { user1: senderId, user2: receiverId }, { user1: receiverId, user2: senderId } ], status: { $in: ['active', 'paused'] } }); if (existingMatch) { throw new Error('Match already exists between these users'); } // Check if there's already a pending request in either direction const existingRequest = await MatchRequest.findOne({ $or: [ { sender: senderId, receiver: receiverId }, { sender: receiverId, receiver: senderId } ], status: 'pending' }); // If receiver already sent a request to sender, create a match if (existingRequest && existingRequest.sender.toString() === receiverId.toString()) { existingRequest.status = 'accepted'; await existingRequest.save(); // Create a new match const newMatch = new Match({ user1: senderId, user2: receiverId, stage: 'text', stageStartDate: new Date(), status: 'active' }); await newMatch.save(); return { matchCreated: true, match: newMatch }; } // If sender already sent a request, return it if (existingRequest) { return { matchCreated: false, request: existingRequest }; } // Create a new match request const newRequest = new MatchRequest({ sender: senderId, receiver: receiverId, status: 'pending', sentAt: new Date() }); await newRequest.save(); return { matchCreated: false, request: newRequest }; } catch (error) { console.error('Error sending match request:', error); throw error; } } /** * Get recommended matches sorted by compatibility * For the app's home screen * * @param {String} userId * @param {Number} limit * @returns {Array} Recommended matches */ async function getRecommendedMatches(userId, limit = 10) { try { const potentialMatches = await findPotentialMatches(userId, limit * 2); // Apply additional filtering and sorting for recommendations const recommendedMatches = potentialMatches // Filter for higher compatibility .filter(match => match.score >= 60) // Sort by mix of compatibility and recency .sort((a, b) => { // Calculate a combined score that weights compatibility (70%) and recency (30%) const recencyScoreA = getRecencyScore(a.user.lastActive); const recencyScoreB = getRecencyScore(b.user.lastActive); const combinedScoreA = (a.score * 0.7) + (recencyScoreA * 0.3); const combinedScoreB = (b.score * 0.7) + (recencyScoreB * 0.3); return combinedScoreB - combinedScoreA; }) .slice(0, limit); return recommendedMatches; } catch (error) { console.error('Error getting recommended matches:', error); throw error; } } /** * Calculate recency score based on user's last activity * Returns a score 0-100 where 100 is most recent * * @param {Date} lastActive * @returns {Number} Recency score 0-100 */ function getRecencyScore(lastActive) { if (!lastActive) return 0; const now = new Date(); const hoursAgo = (now - lastActive) / (1000 * 60 * 60); // Score decreases as hours increase // Users active within last 24 hours get 80-100 // Users active within last week get 50-80 // Users active within last month get 10-50 // Others get 0-10 if (hoursAgo < 24) { return 100 - (hoursAgo / 24 * 20); } else if (hoursAgo < 168) { // 7 days return 80 - ((hoursAgo - 24) / 144 * 30); } else if (hoursAgo < 720) { // 30 days return 50 - ((hoursAgo - 168) / 552 * 40); } else { return Math.max(0, 10 - ((hoursAgo - 720) / 720 * 10)); } } module.exports = { findPotentialMatches, calculateCompatibilityScore, sendMatchRequest, getRecommendedMatches }; javascript Home | My Site 3
top of page

Love

​About Blind Love

Welcome to Blind Love, a unique dating service that prioritizes meaningful conversations. At Blind Love, we believe that genuine connections are built through engaging communication. Join us and experience a new way of finding love.

​Our Approach

At Blind Love, we are committed to fostering relationships based on genuine interactions. Our approach is centered around encouraging users to connect through texts for the first month, allowing them to truly get to know each other without the influence of visual judgments.

Closed Eye_edited.png
Smiley  _edited_edited.png

Your Future Featured Story:

Your Future Featured Story:

Your Future Featured Story:

I found my soulmate through Blind Love. The emphasis on communication allowed us to form a deep bond before ever meeting in person. I highly recommend this service to anyone seeking a meaningful relationship.

Blind Love provided me with the opportunity to connect with someone on a level I hadn't experienced before. The initial focus on conversation allowed us to establish a strong foundation for our relationship.

I was initially skeptical about the concept of Blind Love, but it completely changed my perspective. The emphasis on communication proved to be the key in finding my perfect match.

    The Opposite of Hook-up Culture

Find Your Blind Love Today

Closed Eye_edited_edited.png
​DATING  SITE​

New-Real Connections-Invoative

​

© 2025 by Dating Site. Proudly created with Wix.com.

Featured Story: Tom & Lisa

  • facebook-square
  • Twitter Square
  • google-plus-square
bottom of page