import { InsightError } from "../controller/IInsightFacade"; import { DatasetBuilding, DatasetRoom, DatasetSection, GeoResponse } from "./DatasetSection"; import * as http from "node:http"; export default class DatasetCollector { public collectDataset(section: any): DatasetSection { const { id, Course, Title, Professor, Subject, Avg, Pass, Fail, Audit, Section } = section; let { Year } = section; if (Section === "overall") Year = "1900"; return { uuid: String(id), id: Course, title: Title, instructor: Professor, dept: Subject, year: Number(Year), avg: Avg, pass: Pass, fail: Fail, audit: Audit, } as DatasetSection; } public collectDatasetBuilding(address: string, geo: GeoResponse, trTree: any): DatasetBuilding { const title = this.collectElementByClass(trTree, "views-field-title")[0]; const a = this.collectElementByTag(title, "a")[0]; const fullname = this.collectText(a); const href = this.collectHref(a); const code = this.collectElementByClass(trTree, "views-field-field-building-code")[0]; const shortname = this.collectText(code); const lat = geo.lat; const lon = geo.lon; return { fullname, shortname, address, href, lat, lon, } as DatasetBuilding; } public collectDatasetRoom(trTree: any, building: DatasetBuilding): DatasetRoom { const fullname = building.fullname; const shortname = building.shortname; const address = building.address; const lat = building.lat; const lon = building.lon; const roomNumber = this.collectElementByClass(trTree, "views-field-field-room-number")[0]; const a = this.collectElementByTag(roomNumber, "a")[0]; const href = this.collectHref(a); const number = this.collectText(a); const name = shortname + "_" + number; const roomType = this.collectElementByClass(trTree, "views-field-field-room-type")[0]; const type = this.collectText(roomType); const roomFurniture = this.collectElementByClass(trTree, "views-field-field-room-furniture")[0]; const furniture = this.collectText(roomFurniture); const roomCapacity = this.collectElementByClass(trTree, "views-field-field-room-capacity")[0]; const seats = Number(this.collectText(roomCapacity)); return { fullname, shortname, address, href, lat, lon, number, name, type, furniture, seats, } as DatasetRoom; } public collectElementByTag(content: any, value: string): any { const elements = []; if (content.tagName === value) { elements.push(content); } if (content.childNodes) { for (const childNode of content.childNodes) { const res = this.collectElementByTag(childNode, value); elements.push(...res); } } return elements; } public collectElementByClass(content: any, value: string): any { const elements = []; const attrCheck = content.attrs?.filter((attr: any) => attr.name === "class"); if (attrCheck?.length) { const classList = new Set(attrCheck[0].value.split(" ")); if (classList.has(value)) { elements.push(content); } } if (content.childNodes) { for (const childNode of content.childNodes) { const res = this.collectElementByClass(childNode, value); elements.push(...res); } } return elements; } public collectText(content: any): string { for (const childNode of content.childNodes) { if (childNode.nodeName === "#text") { return String(childNode.value).trim(); } } throw new InsightError(`collectText`); } public collectHref(content: any): string { return content.attrs?.find((attr: any) => attr.name === "href")?.value; } // adapted from https://blog.logrocket.com/5-ways-make-http-requests-node-js/ public async collectGeoResponse(address: string): Promise { const code = encodeURIComponent(address); return new Promise((resolve) => { http .get(`http://cs310.students.cs.ubc.ca:11316/api/v1/project_team285/${code}`, (res) => { const data: any[] = []; res.on("data", (chunk) => { data.push(chunk); }); res.on("end", () => { try { resolve(JSON.parse(Buffer.concat(data).toString())); } catch (_err) { resolve({ error: "collectGeoResponse" } as GeoResponse); } }); }) .on("error", (err) => { resolve({ error: err.message } as GeoResponse); }); }); } }