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<GeoResponse> {
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);
});
});
}
}