diff --git a/server/harmonize.py b/server/harmonize.py index 9e40cc4..2a111c6 100644 --- a/server/harmonize.py +++ b/server/harmonize.py @@ -114,7 +114,13 @@ else: class_data["sched"].extend(class_sem["sched"]) class_data["terms"].append(class_sem["term"]) - class_data["instructor"][class_sem["term"]] = class_sem["instructor"] + + # formatting instructor names to only First Last + instrs = [] + for instr in class_sem["instructor"]: + instrs.append(instr.split(" ")[0] + " " + instr.split(" ")[-1]) + class_data["instructor"][class_sem["term"]] = instrs + if " { }; - // Helper function to format instructor name - function formatInstructorName(name) { - if (name === "TBA") return 'TBA'; - const splitName = name.split(' '); - const lastName = splitName.pop(); - const firstName = splitName.shift(); - const middleName = splitName.join(' '); - if (middleName.length >= 1) { - splitName[0] = middleName[0] + '.'; - } - return `${lastName}, ${firstName}${splitName.length > 0 ? ' ' + splitName.join(' ') : ''}`; - } - - useEffect(() => { if (!course) return; // @unkn-wn @knightron0 delete this comment after review: @@ -84,14 +70,13 @@ const FullInstructorModal = ({ isOpen, onClose, course }) => { for (const semester in course.instructor) { consolidatedData[semester] = {}; for (const instructor of course.instructor[semester]) { - const formattedInstructor = formatInstructorName(instructor); let gpa = "No GPA"; let color = getColor(0); - if (course.gpa[formattedInstructor] && course.gpa[formattedInstructor][semester]) { - gpa = course.gpa[formattedInstructor][semester][13] || "No GPA"; - color = getColor(course.gpa[formattedInstructor][semester][13] || 0); + if (course.gpa[instructor] && course.gpa[instructor][semester]) { + gpa = course.gpa[instructor][semester][13] || "No GPA"; + color = getColor(course.gpa[instructor][semester][13] || 0); } - consolidatedData[semester][formattedInstructor] = { + consolidatedData[semester][instructor] = { gpa: gpa, color: color }; diff --git a/src/components/infoModal.js b/src/components/infoModal.js index 47f7609..eb9991c 100644 --- a/src/components/infoModal.js +++ b/src/components/infoModal.js @@ -41,7 +41,7 @@ const InfoModal = ({ isOpen, onClose }) => { The last instructor selected represents the Average GPA and RateMyProfessors Rating on the circle graphs! To view a different average GPA or RateMyProfessor (RMP) rating, click the instructor dropdown and select a different instructor.

- Sometimes, the GPA data or RMP rating my not be available for a specific instructor, and may be blank. + Sometimes, the RateMyProfessor rating may take a moment to load.

To view all instructor GPAs, click on the "Average GPA" circle graph. It will display the breakdown of each professor's GPA per semester. 0 means that the professor has not taught that semester. diff --git a/src/pages/detail/[id].js b/src/pages/detail/[id].js index 5116aa1..763bb43 100644 --- a/src/pages/detail/[id].js +++ b/src/pages/detail/[id].js @@ -2,7 +2,7 @@ import { Inter } from 'next/font/google' import { semesters, subjects } from "../../lib/utils" const inter = Inter({ subsets: ['latin'] }) import { useRouter } from 'next/router'; -import { useEffect, useState } from 'react'; +import { useEffect, useState, useRef } from 'react'; import ErrorPage from 'next/error' import Select from 'react-select'; @@ -68,23 +68,31 @@ const CardDetails = ({ courseData, semData }) => { } - // Helper function to format instructor name - function formatInstructorName(name) { - if (name === "TBA") return 'TBA'; - const splitName = name.split(' '); - const lastName = splitName.pop(); - const firstName = splitName.shift(); - const middleName = splitName.join(' '); - if (middleName.length >= 1) { - splitName[0] = middleName[0] + '.'; - } - return `${lastName}, ${firstName}${splitName.length > 0 ? ' ' + splitName.join(' ') : ''}`; - } + // Helper function to format instructor name to "Middle middle Last, First" + // or Last, First M. for some reason cause our data isnt fucking consolidated @Sarthak + // function formatInstructorName(name) { + // if (name === "TBA") return 'TBA'; + // const splitName = name.split(' '); + + // if (splitName.length > 3) { + // const firstName = splitName[0]; + // const rest = splitName.slice(1).join(' '); + // return `${rest}, ${firstName}`; + // } else { + // const lastName = splitName.pop(); + // const firstName = splitName.shift(); + // const middleName = splitName.join(' '); + // if (middleName.length >= 1) { + // splitName[0] = middleName[0] + '.'; + // } + // return `${lastName}, ${firstName}${splitName.length > 0 ? ' ' + splitName.join(' ') : ''}`; + // } + // } useEffect(() => { if (!course) return; - console.log(JSON.stringify(course, null, 2)); // for debugging and you dont wanna start server + // console.log(JSON.stringify(course, null, 2)); // for debugging and you dont wanna start server // set descriptions to none if it's html if (course.description && course.description.startsWith("
{ // Refresh graph when instructors change const refreshGraph = (instructors) => { const gpa = defaultGPA.datasets; - if (!gpa || gpa.length === 0 || !instructors ) return; + if (!gpa || gpa.length === 0 || !instructors) return; setFirstInstructor(" "); try { @@ -331,61 +352,84 @@ const CardDetails = ({ courseData, semData }) => { // Function to get link for RMP on the dial graph - function getFormattedName(instructor) { - if (!instructor) return ''; // Check if instructor is provided - const nameParts = instructor.split(", "); - if (nameParts.length < 2) return ''; // Check if split operation succeeded - const firstName = nameParts[1].split(" ")[0]; - const lastName = nameParts[0]; - return `${firstName} ${lastName}`; - } + // function formatInstructorNameRMP(instructor) { + // if (!instructor) return ''; // Check if instructor is provided + // const nameParts = instructor.split(", "); + // if (nameParts.length < 2) return ''; // Check if split operation succeeded + // const firstName = nameParts[1].split(" ")[0]; + // const splitName = nameParts[0].split(" "); + // const lastName = splitName[splitName.length - 1]; + + // // splits from "Middle middle Last, First" to "First Last" + // return `${firstName} ${lastName}`; + // } - // Get RateMyProfessor ratings for instructor - async function getRMPRating(instructor) { - if (!instructor) return; + // Batched RMP ratings fetch for allProfs + async function getAllRMPRatings(allProfs) { + if (!Array.isArray(allProfs) || allProfs.length === 0) return {}; - // Instructor in format "Last, First Middle", convert to "First Last" - let instructorSplit = []; - try { - instructorSplit = instructor.split(", "); - instructorSplit.push(instructorSplit[1].split(" ")[0]); - } catch { - return; + const batchSize = 10; // Number of requests to send in each batch + const batches = []; // Array to hold batches of professors + const ratings = {}; // Object to store ratings + + // Split allProfs into batches + for (let i = 0; i < allProfs.length; i += batchSize) { + batches.push(allProfs.slice(i, i + batchSize)); } - const name = instructorSplit[2] + " " + instructorSplit[0]; + // Process batches in parallel + await Promise.all( + batches.map(async (batch) => { + const ratingsBatch = await Promise.all(batch.map((instructor) => getRMPRating(instructor))); + batch.forEach((instructor, index) => { + ratings[instructor] = ratingsBatch[index]; + }); + }) + ); + + return ratings; + } + + + // Get RateMyProfessor ratings for instructor + async function getRMPRating(instructor) { + if (!instructor) return 0; try { - const params = new URLSearchParams({ q: "Purdue University" }); - const responseSchools = await fetch("/api/ratings/searchSchool?" + params); - const schools = await responseSchools.json(); - - const profs = []; - - for (const school of schools["schools"]) { - if (school.city === "West Lafayette") { - const paramsTeacher = new URLSearchParams({ name: name, id: school.id }); - const responseProf = await fetch("/api/ratings/searchTeacher?" + paramsTeacher); - const prof = await responseProf.json() - if (!(prof["prof"] === undefined || prof["prof"].length == 0)) { - profs.push(...prof["prof"]); - } + // TO SEARCH FOR "PURDUE UNIVERSITY" + // const params = new URLSearchParams({ q: "Purdue University" }); + // const responseSchools = await fetch("/api/ratings/searchSchool?" + params); + // const schools = await responseSchools.json(); + // const purdues = schools.schools.filter(school => school.city === "West Lafayette"); + + let rating = 0; + + // for all Purdue University schools in West Lafayette, search prof + const schools = ["U2Nob29sLTc4Mw==", "U2Nob29sLTE3NTk5"]; // purdue IDs for West Lafayette + for (const school of schools) { + const paramsTeacher = new URLSearchParams({ name: instructor, id: school }); + const responseProf = await fetch("/api/ratings/searchTeacher?" + paramsTeacher); + const prof = await responseProf.json(); + const profs = prof.prof.filter(Boolean); + + if (profs.length > 0) { + const paramsGetTeacher = new URLSearchParams({ id: profs[0].id }); + const responseRMP = await fetch("/api/ratings/getTeacher?" + paramsGetTeacher); + const RMPrating = await responseRMP.json(); + rating = RMPrating.RMPrating.avgRating; + break; } } - if (profs.length === 0) return 0; - const paramsGetTeacher = new URLSearchParams({ id: profs[0].id }); - const responseRMP = await fetch("/api/ratings/getTeacher?" + paramsGetTeacher); - const RMPrating = await responseRMP.json(); - return RMPrating["RMPrating"].avgRating; - } catch { - return; + return rating; + } catch (error) { + console.error(error); + return 0; } - - } + if (JSON.stringify(course) == '{}') { return } @@ -461,7 +505,7 @@ const CardDetails = ({ courseData, semData }) => { } /> - + @@ -648,9 +692,18 @@ const CardDetails = ({ courseData, semData }) => {

Average GPA

-
+ + {/* For when there is no RMP data for firstInstructor */} + {firstInstructor && (!curRMP[firstInstructor] || curRMP[firstInstructor] === 0) && +
+

No rating available for {firstInstructor}

+

Click on this to open RMP!

+
+ } +