/** * Car Database Service * Handles all car data operations and queries */ import { Car, CarFilter, CarComparison, CarInventory } from './carTypes'; export class CarDatabase { private cars: Car[] = []; /** * Initialize database with sample data */ initialize(cars: Car[]): void { this.cars = cars; } /** * Get all cars */ getAllCars(): Car[] { return this.cars; } /** * Get car by ID */ getCarById(id: string): Car | undefined { return this.cars.find((car) => car.id === id); } /** * Search cars by filter criteria */ filterCars(filter: CarFilter): Car[] { return this.cars.filter((car) => { // Make filter if (filter.make && !filter.make.includes(car.make)) { return false; } // Model filter if (filter.model && !filter.model.includes(car.model)) { return false; } // Year range filter if (filter.yearRange) { const [minYear, maxYear] = filter.yearRange; if (car.year < minYear || car.year > maxYear) { return false; } } // Price range filter if (filter.priceRange) { const [minPrice, maxPrice] = filter.priceRange; if (car.price < minPrice || car.price > maxPrice) { return false; } } // Transmission filter if (filter.transmission && !filter.transmission.includes(car.transmission)) { return false; } // Fuel filter if (filter.fuel && !filter.fuel.includes(car.fuel)) { return false; } // Body type filter if (filter.bodyType && !filter.bodyType.includes(car.bodyType || '')) { return false; } // Drive type filter if (filter.driveType && !filter.driveType.includes(car.driveType || '')) { return false; } // Seating filter if (filter.seatCount && car.seating) { const [minSeats, maxSeats] = filter.seatCount; if (car.seating < minSeats || car.seating > maxSeats) { return false; } } // Safety rating filter if (filter.safetyRating && car.safetyRating && car.safetyRating < filter.safetyRating) { return false; } // Keyword search if (filter.keyword) { const keyword = filter.keyword.toLowerCase(); const searchableFields = [ car.make, car.model, car.bodyType, car.color, car.description, ].filter(Boolean); const matches = searchableFields.some( (field) => field && field.toString().toLowerCase().includes(keyword) ); if (!matches) { return false; } } return true; }); } /** * Search cars by keyword */ searchCars(keyword: string): Car[] { return this.filterCars({ keyword }); } /** * Get cars by make */ getCarsByMake(make: string): Car[] { return this.cars.filter((car) => car.make.toLowerCase() === make.toLowerCase()); } /** * Get cars by fuel type */ getCarsByFuel(fuel: string): Car[] { return this.cars.filter((car) => car.fuel === fuel); } /** * Get cars by body type */ getCarsByBodyType(bodyType: string): Car[] { return this.cars.filter((car) => car.bodyType === bodyType); } /** * Get cars within price range */ getCarsByPriceRange(minPrice: number, maxPrice: number): Car[] { return this.cars.filter((car) => car.price >= minPrice && car.price <= maxPrice); } /** * Sort cars by field */ sortCars(cars: Car[], sortBy: keyof Car, ascending: boolean = true): Car[] { const sorted = [...cars].sort((a, b) => { const aValue = a[sortBy]; const bValue = b[sortBy]; if (typeof aValue === 'number' && typeof bValue === 'number') { return ascending ? aValue - bValue : bValue - aValue; } if (typeof aValue === 'string' && typeof bValue === 'string') { return ascending ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); } return 0; }); return sorted; } /** * Get unique makes */ getUniqueMakes(): string[] { const makes = new Set(this.cars.map((car) => car.make)); return Array.from(makes).sort(); } /** * Get unique models for a make */ getUniqueModels(make: string): string[] { const models = new Set( this.cars.filter((car) => car.make === make).map((car) => car.model) ); return Array.from(models).sort(); } /** * Get unique fuel types */ getUniqueFuelTypes(): string[] { const fuels = new Set(this.cars.map((car) => car.fuel)); return Array.from(fuels).sort(); } /** * Get unique body types */ getUniqueBodyTypes(): string[] { const bodyTypes = new Set(this.cars.filter((car) => car.bodyType).map((car) => car.bodyType)); return Array.from(bodyTypes).sort(); } /** * Compare two or more cars */ compareCars(carIds: string[]): Car[] { return carIds .map((id) => this.getCarById(id)) .filter((car) => car !== undefined) as Car[]; } /** * Get similar cars based on specifications */ getSimilarCars(carId: string, count: number = 3): Car[] { const car = this.getCarById(carId); if (!car) return []; const similar = this.cars .filter((c) => c.id !== carId && c.make === car.make) .slice(0, count); return similar.length >= count ? similar : this.cars.filter((c) => c.id !== carId && c.bodyType === car.bodyType).slice(0, count); } /** * Get top rated cars */ getTopRatedCars(count: number = 5): Car[] { return [...this.cars] .sort((a, b) => (b.userRating || 0) - (a.userRating || 0)) .slice(0, count); } /** * Get most viewed cars */ getMostViewedCars(count: number = 5): Car[] { return [...this.cars] .sort((a, b) => (b.viewCount || 0) - (a.viewCount || 0)) .slice(0, count); } /** * Get featured cars */ getFeaturedCars(count: number = 5): Car[] { return this.cars.filter((car) => car.isFavorite).slice(0, count); } /** * Calculate average specifications for a make or body type */ calculateAverageSpecs( cars: Car[] ): Partial { if (cars.length === 0) return {}; const specs: Partial = { price: cars.reduce((sum, car) => sum + car.price, 0) / cars.length, horsepower: cars.reduce((sum, car) => sum + (car.horsepower || 0), 0) / cars.length, mpg: cars.reduce((sum, car) => sum + (car.mpg || 0), 0) / cars.length, seating: Math.round(cars.reduce((sum, car) => sum + (car.seating || 0), 0) / cars.length), }; return specs; } /** * Add a new car to database */ addCar(car: Car): void { this.cars.push(car); } /** * Update a car */ updateCar(id: string, updates: Partial): Car | undefined { const index = this.cars.findIndex((car) => car.id === id); if (index !== -1) { this.cars[index] = { ...this.cars[index], ...updates, updatedAt: new Date() }; return this.cars[index]; } return undefined; } /** * Delete a car */ deleteCar(id: string): boolean { const index = this.cars.findIndex((car) => car.id === id); if (index !== -1) { this.cars.splice(index, 1); return true; } return false; } /** * Get database statistics */ getStatistics() { return { totalCars: this.cars.length, averagePrice: this.cars.reduce((sum, car) => sum + car.price, 0) / this.cars.length, makes: this.getUniqueMakes().length, models: this.cars.length, fuelTypes: this.getUniqueFuelTypes().length, bodyTypes: this.getUniqueBodyTypes().length, averageHorsepower: this.cars.reduce((sum, car) => sum + (car.horsepower || 0), 0) / this.cars.length, averageMpg: this.cars.reduce((sum, car) => sum + (car.mpg || 0), 0) / this.cars.length, }; } } // Export singleton instance export const carDatabase = new CarDatabase();