diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..b7b1aff --- /dev/null +++ b/.dockerignore @@ -0,0 +1,52 @@ +# dependencies +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# build output +dist/ +build/ +out/ +coverage/ + +# environment files +.env +.env.local +.env.*.local + +# logs +logs/ +*.log +pids/ +*.pid +*.pid.lock + +# runtime data +*.sock + +# editor directories and files +.vscode/ +.idea/ +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# OS files +.DS_Store +Thumbs.db + +# Docker itself +Dockerfile* +docker-compose*.yml + +# bundle artifacts +*.tgz + +# test output +test-results/ + +# other +coverage/ diff --git a/.gitignore b/.gitignore index ceaea36..1a2979b 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,4 @@ dist .yarn/install-state.gz .pnp.* +.venv \ No newline at end of file diff --git a/app.js b/app.js index bc8d854..44a8ffb 100644 --- a/app.js +++ b/app.js @@ -9,7 +9,7 @@ const app = express(); require('dotenv').config(); const port = process.env.PORT || 5000; -const connectDB = require('./src/db/connectDB'); +const connectDB = require('./src/db/connectDB'); connectDB(); app.use(express.json()); diff --git a/nhtsa_jp.py b/nhtsa_jp.py new file mode 100644 index 0000000..dae7c8b --- /dev/null +++ b/nhtsa_jp.py @@ -0,0 +1,112 @@ +# nhtsa_japan_domestic.py + +import os +import requests +from pymongo import MongoClient, ASCENDING +from typing import List, Dict, Set + +BASE_URL = 'https://vpic.nhtsa.dot.gov/api/vehicles' +FMT = 'format=json' + +# — MongoDB setup +MONGO_URI = os.getenv('MONGO_URI', 'mongodb+srv://goldfishjonny:Tt0BBMbzai477RIM@csc491.g36va.mongodb.net/') +MONGO_DB = os.getenv('MONGO_DB', 'RevSocial') +client = MongoClient(MONGO_URI) +db = client[MONGO_DB] + +# — Collections & Indexes +makes_col = db['jdm_makes'] +models_col = db['jdm_models'] + +makes_col .create_index('make_name', unique=True) +models_col.create_index([('make',ASCENDING), + ('year',ASCENDING), + ('model',ASCENDING)], unique=True) + +def get_all_manufacturers(page: int=1) -> List[Dict]: + """/vehicles/GetAllManufacturers?page={page}&format=json :contentReference[oaicite:0]{index=0}""" + r = requests.get(f'{BASE_URL}/GetAllManufacturers?{FMT}&page={page}') + r.raise_for_status() + return r.json()['Results'] + +def get_makes_for_manufacturer(mfr_id: int) -> List[Dict]: + """/vehicles/GetMakeForManufacturer/{mfr_id}?format=json :contentReference[oaicite:1]{index=1}""" + r = requests.get(f'{BASE_URL}/GetMakeForManufacturer/{mfr_id}?{FMT}') + r.raise_for_status() + return r.json()['Results'] + +def produces_strict_passenger_car(make: str) -> bool: + """ + Only count if VehicleTypeName == "Passenger Car" exactly. + /vehicles/GetVehicleTypesForMake/{make}?format=json :contentReference[oaicite:2]{index=2} + """ + r = requests.get( + f'{BASE_URL}/GetVehicleTypesForMake/{requests.utils.quote(make)}?{FMT}' + ) + r.raise_for_status() + types = [v['VehicleTypeName'].strip().lower() + for v in r.json()['Results']] + return 'passenger car' in types + +def seed_jdm_makes() -> List[str]: + """ + Find all Japanese manufacturers, then their makes that + strictly produce Passenger Cars in the JDM market. + """ + jdm_makes: Set[str] = set() + page = 1 + while True: + mfrs = get_all_manufacturers(page) + if not mfrs: + break + + # only Japan‐based manufacturers + jap = [m for m in mfrs if m.get('Country','').lower() == 'japan'] + if not jap: + # no more Japan entries further on + break + + for m in jap: + for mk in get_makes_for_manufacturer(m['Mfr_ID']): + name = mk['Make_Name'] + if produces_strict_passenger_car(name): + jdm_makes.add(name) + makes_col.update_one( + {'make_name': name}, + {'$set': {'make_name': name}}, + upsert=True + ) + page += 1 + + return sorted(jdm_makes) + +def seed_models_for_years(makes: List[str], years: List[int]): + """ + For each JDM make, seed models_by_year documents. + /vehicles/GetModelsForMakeYear/make/{make}/modelyear/{year}?format=json :contentReference[oaicite:3]{index=3} + """ + for make in makes: + for yr in years: + url = ( + f'{BASE_URL}/GetModelsForMakeYear/' + f'make/{requests.utils.quote(make)}/modelyear/{yr}?{FMT}' + ) + r = requests.get(url) + r.raise_for_status() + models = [m['Model_Name'] for m in r.json()['Results']] + for model in models: + models_col.update_one( + {'make': make, 'year': yr, 'model': model}, + {'$set': {'make': make, 'year': yr, 'model': model}}, + upsert=True + ) + print(f"{yr} {make}: {len(models)} models") + +if __name__ == '__main__': + print("Seeding JDM makes…") + jdm = seed_jdm_makes() + print(f"→ {len(jdm)} Japanese domestic‐market makes stored in '{MONGO_DB}.jdm_makes'") + + YEARS = list(range(2015, 2026)) + seed_models_for_years(jdm, YEARS) + print("Done seeding Japanese domestic cars.") \ No newline at end of file diff --git a/src/controllers/carsController.js b/src/controllers/carsController.js new file mode 100644 index 0000000..9d1acda --- /dev/null +++ b/src/controllers/carsController.js @@ -0,0 +1,16 @@ +const CarMake = require('../models/car_makes.js'); + +// Get all makes +// This function retrieves all car makes from the database and sends them as a response. +exports.getMakes = async (req, res) =>{ + try { + const makes = await CarMake.find() + res.status(200).json(makes); + + } catch (error) { + res.status(500).json({ + message: 'Server error retrieving makes', + error: error.message + }); + } +}; \ No newline at end of file diff --git a/src/controllers/userController.js b/src/controllers/userController.js index 1dd7012..14dc4a6 100644 --- a/src/controllers/userController.js +++ b/src/controllers/userController.js @@ -1,6 +1,4 @@ const User = require('../models/user'); -const bcrypt = require('bcryptjs'); -const jwt = require('jsonwebtoken'); // Get single user by ID exports.getUser = async (req, res) => { diff --git a/src/models/car_makes.js b/src/models/car_makes.js new file mode 100644 index 0000000..ddaf4d5 --- /dev/null +++ b/src/models/car_makes.js @@ -0,0 +1,10 @@ +const { Schema, model } = require('mongoose'); + +const carMakeSchema = new Schema( + { + make_name: { + type: String + } + }); + +model.exports = model('CarMake', carMakeSchema); \ No newline at end of file diff --git a/src/routes/v1/carsRoutes.js b/src/routes/v1/carsRoutes.js new file mode 100644 index 0000000..f33d64b --- /dev/null +++ b/src/routes/v1/carsRoutes.js @@ -0,0 +1,5 @@ +const express = require('express'); +const router = express.Router(); +const {getMakes} = require('../../controllers/carsController'); + +router.get('/makes', getMakes); \ No newline at end of file