-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.js
112 lines (99 loc) · 3.34 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
const request = require('request-promise');
const _ = require('lodash');
const BodyStyles = require('./enums/BodyStyles');
const FuelTypes = require('./enums/FuelTypes');
const generateRequestOptions = (options = {}) => {
_.defaults(options, {
bodyStyles: BodyStyles.ALL,
fuelTypes: FuelTypes.ALL,
minPrice: 10000,
maxPrice: 20000,
zipCode: 30305
});
const { bodyStyles, fuelTypes, minPrice, maxPrice, zipCode } = options;
let payload = {
sortBy: "LowestPrice",
pagination: {
page: 1,
pageSize: 10000
},
filters: {
bodyStyles,
fuelTypes,
price: {
min: minPrice,
max: maxPrice
}
},
searchContext: {
mostPopularSortOption: 1,
geolocationInfo: {
location: {
zip5: zipCode
}
}
}
};
if (options.bodyStyles === BodyStyles.ALL) {
delete payload.filters.bodyStyles;
}
if (options.fuelTypes === FuelTypes.ALL) {
delete payload.filters.fuelTypes;
}
return payload;
};
const getVehicles = (options = {}) => {
const requestOptions = generateRequestOptions(_.defaults(options, { fuelTypes: FuelTypes.ALL, bodyStyles: BodyStyles.ALL }));
return request({
uri: "https://www.carvana.com/api/v1/inventory",
method: "POST",
body: JSON.stringify(requestOptions),
transform: JSON.parse,
headers: {
// The only authentication they have is requiring a non ROBOTS User-Agent
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.91 Safari/537.36'
}
}).then(json => {
const { inventory } = json;
console.log(`Found ${inventory.pagination.totalMatchedInventory} Cars`);
return inventory.vehicles;
}).catch(err => {
console.log(err);
});
};
const vehicleIsHybrid = vehicle => vehicle.model.includes(/Hybrid|Prius|Niro|Ioniq/);
const filterToHybrids = vehicles => {
console.log(`Filtering down to Hybrids...`);
return vehicles.filter(vehicleIsHybrid);
};
const filterToNonPendingPurchase = vehicles => {
console.log(`Removing pending purchases...`);
return vehicles.filter(vehicle => ! vehicle.isPendingPurchase);
};
const debug = vehicles => vehicles.map(vehicle => console.log(vehicle) && vehicle);
const transformVehicleJSON = vehicle => ({
make: vehicle.make,
model: vehicle.model,
trim: vehicle.trim,
mileage: vehicle.mileage,
year: vehicle.year,
sku: vehicle.stockNumber,
totalCost: Number(vehicle.price.total) + (Number(vehicle.price.transportCost) || 0)
});
const average = (vehicles, key) => Math.floor(_.meanBy(vehicles, v => v[key]));
const groupByMakeAndModel = vehicles => _.groupBy(vehicles, vehicle => `${vehicle.make} ${vehicle.model}`);
getVehicles({ bodyStyles: BodyStyles.SEDAN })
.then(filterToNonPendingPurchase)
.then(vehicles => vehicles.map(transformVehicleJSON))
.then(vehicles => {
console.log(`Found ${vehicles.length} Vehicles`);
const grouped = groupByMakeAndModel(vehicles);
Object.keys(grouped).map(type => {
const filtered = grouped[type];
console.log('--------------------------')
console.log(`${type}: ${filtered.length} car(s)`)
console.log(`Average Year: ${average(filtered, 'year')}`)
console.log(`Average Mileage: ${average(filtered, 'mileage')}`)
console.log(`Average Cost: ${average(filtered, 'totalCost')}`)
});
});