mirror of
https://github.com/mblanke/holiday-travel-app.git
synced 2026-03-01 13:30:20 -05:00
Initial commit: Holiday Travel App with resort comparison, trip management, and multi-provider search
This commit is contained in:
70
lib/score.ts
Normal file
70
lib/score.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import type { Deal, TravelPreferences } from "./types";
|
||||
|
||||
// Destination feature profiles (0-10 ratings for common destinations)
|
||||
const DESTINATION_PROFILES: Record<string, TravelPreferences> = {
|
||||
// Caribbean
|
||||
"CUN": { beach: 10, pool: 9, golf: 6, spa: 8, food: 8, nightlife: 9, shopping: 7, culture: 5, outdoor: 8, family: 9 },
|
||||
"PUJ": { beach: 10, pool: 9, golf: 7, spa: 8, food: 7, nightlife: 8, shopping: 6, culture: 4, outdoor: 7, family: 9 },
|
||||
"MBJ": { beach: 10, pool: 8, golf: 5, spa: 7, food: 8, nightlife: 7, shopping: 5, culture: 6, outdoor: 9, family: 8 },
|
||||
"NAS": { beach: 9, pool: 8, golf: 6, spa: 6, food: 7, nightlife: 8, shopping: 7, culture: 5, outdoor: 8, family: 8 },
|
||||
|
||||
// Europe
|
||||
"LHR": { beach: 2, pool: 5, golf: 6, spa: 7, food: 9, nightlife: 8, shopping: 10, culture: 10, outdoor: 6, family: 7 },
|
||||
"CDG": { beach: 1, pool: 6, golf: 5, spa: 8, food: 10, nightlife: 9, shopping: 10, culture: 10, outdoor: 5, family: 7 },
|
||||
"FCO": { beach: 3, pool: 6, golf: 4, spa: 7, food: 10, nightlife: 8, shopping: 9, culture: 10, outdoor: 7, family: 8 },
|
||||
"BCN": { beach: 8, pool: 7, golf: 5, spa: 7, food: 9, nightlife: 10, shopping: 8, culture: 9, outdoor: 7, family: 7 },
|
||||
"AMS": { beach: 1, pool: 5, golf: 4, spa: 6, food: 8, nightlife: 9, shopping: 8, culture: 9, outdoor: 6, family: 7 },
|
||||
|
||||
// USA
|
||||
"LAX": { beach: 8, pool: 7, golf: 7, spa: 8, food: 9, nightlife: 9, shopping: 9, culture: 8, outdoor: 8, family: 7 },
|
||||
"LAS": { beach: 0, pool: 9, golf: 8, spa: 10, food: 9, nightlife: 10, shopping: 10, culture: 5, outdoor: 5, family: 6 },
|
||||
"MIA": { beach: 9, pool: 8, golf: 7, spa: 8, food: 8, nightlife: 10, shopping: 9, culture: 7, outdoor: 8, family: 7 },
|
||||
"MCO": { beach: 5, pool: 10, golf: 8, spa: 7, food: 7, nightlife: 7, shopping: 8, culture: 6, outdoor: 6, family: 10 },
|
||||
"HNL": { beach: 10, pool: 8, golf: 9, spa: 8, food: 8, nightlife: 7, shopping: 7, culture: 8, outdoor: 10, family: 9 },
|
||||
|
||||
// Default fallback
|
||||
"DEFAULT": { beach: 5, pool: 5, golf: 5, spa: 5, food: 5, nightlife: 5, shopping: 5, culture: 5, outdoor: 5, family: 5 }
|
||||
};
|
||||
|
||||
function calculatePreferenceMatch(deal: Deal, preferences?: TravelPreferences): number {
|
||||
if (!preferences || !deal.destination) return 0;
|
||||
|
||||
const destProfile = DESTINATION_PROFILES[deal.destination.toUpperCase()] || DESTINATION_PROFILES["DEFAULT"];
|
||||
let matchScore = 0;
|
||||
let totalWeight = 0;
|
||||
|
||||
// Calculate how well the destination matches user preferences
|
||||
for (const [feature, userRating] of Object.entries(preferences)) {
|
||||
if (userRating && userRating > 0) {
|
||||
const destRating = destProfile[feature as keyof TravelPreferences] || 5;
|
||||
// Higher user rating + higher destination rating = better match
|
||||
matchScore += (userRating * destRating);
|
||||
totalWeight += (userRating * 10); // max possible for this feature
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize to 0-1000 scale
|
||||
if (totalWeight > 0) {
|
||||
return (matchScore / totalWeight) * 1000;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function scoreDeal(d: Deal, preferences?: TravelPreferences): number {
|
||||
// Very simple scoring: prefer lower price, direct, reasonable nights
|
||||
let score = 0;
|
||||
if (typeof d.price === "number") score += Math.max(0, 10000 - d.price);
|
||||
if (d.stops === 0) score += 500;
|
||||
if (typeof d.nights === "number") {
|
||||
const target = 7;
|
||||
score += Math.max(0, 300 - Math.abs(d.nights - target) * 40);
|
||||
}
|
||||
if (d.source.includes("Deals")) score += 150; // curated deal sites
|
||||
|
||||
// Add preference matching bonus
|
||||
const preferenceBonus = calculatePreferenceMatch(d, preferences);
|
||||
score += preferenceBonus;
|
||||
|
||||
return score;
|
||||
}
|
||||
Reference in New Issue
Block a user