Skip to content

Commit

Permalink
fix avg rating
Browse files Browse the repository at this point in the history
  • Loading branch information
js0mmer committed Nov 11, 2024
1 parent a4a1b8d commit 5def90b
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 28 deletions.
7 changes: 3 additions & 4 deletions api/src/controllers/reviews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { TRPCError } from '@trpc/server';
import { db } from '../db';
import { review, user, vote } from '../db/schema';
import { and, count, desc, eq, sql } from 'drizzle-orm';
import { and, avg, count, desc, eq, sql } from 'drizzle-orm';
import { datesToStrings } from '../helpers/date';

async function userWroteReview(userId: number | undefined, reviewId: number) {
Expand Down Expand Up @@ -224,17 +224,16 @@ const reviewsRouter = router({
/**
* Get avg ratings for a course's professors or a professor's courses
*/
scores: publicProcedure
avgRating: publicProcedure
.input(z.object({ type: z.enum(['course', 'professor']), id: z.string() }))
.query(async ({ input }) => {
const field = input.type === 'course' ? review.courseId : review.professorId;
const otherField = input.type === 'course' ? review.professorId : review.courseId;

const results = await db
.select({ name: otherField, score: sql`COALESCE(SUM(${vote.vote}), 0)`.mapWith(Number) })
.select({ name: otherField, avgRating: avg(review.rating).mapWith(Number) })
.from(review)
.where(eq(field, input.id))
.leftJoin(vote, eq(vote.reviewId, review.id))
.groupBy(otherField);

return results;
Expand Down
8 changes: 6 additions & 2 deletions site/src/component/SearchPopup/SearchPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,15 @@ const SearchPopupContent: FC<SearchPopupProps> = (props) => {
<div key={`search-popup-carousel-${i}`} className="search-popup-carousel search-popup-block">
<div>
<span className="search-popup-carousel-score">
{score.score == -1 ? '?' : Number.isInteger(score.score) ? score.score : score.score.toFixed(2)}
{score.avgRating == -1
? '?'
: Number.isInteger(score.avgRating)
? score.avgRating
: score.avgRating.toFixed(2)}
</span>
<span className="search-popup-carousel-max-score">/ 5.0</span>
</div>
<Link to={`/${props.searchType == 'course' ? 'professor' : 'course'}/${score.key}`}>
<Link to={`/${props.searchType == 'course' ? 'professor' : 'course'}/${score.id}`}>
{score.name}
</Link>
</div>
Expand Down
12 changes: 8 additions & 4 deletions site/src/pages/SearchPage/CoursePopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,28 @@ const CoursePopup: FC = () => {

useEffect(() => {
if (course) {
trpc.reviews.scores.query({ type: 'course', id: course.id }).then((res) => {
trpc.reviews.avgRating.query({ type: 'course', id: course.id }).then((res) => {
const scores: ScoreData[] = [];
// set of ucinetid professors with scores
const scoredProfessors = new Set(res.map((v) => v.name));
// add known scores
res.forEach((entry) => {
if (course.instructors[entry.name]) {
scores.push({ name: course.instructors[entry.name].shortenedName, score: entry.score, key: entry.name });
scores.push({
name: course.instructors[entry.name].shortenedName,
avgRating: entry.avgRating,
id: entry.name,
});
}
});
// add unknown score
Object.keys(course.instructors).forEach((ucinetid) => {
if (!scoredProfessors.has(ucinetid)) {
scores.push({ name: course.instructors[ucinetid].shortenedName, score: -1, key: ucinetid });
scores.push({ name: course.instructors[ucinetid].shortenedName, avgRating: -1, id: ucinetid });
}
});
// sort by highest score
scores.sort((a, b) => b.score - a.score);
scores.sort((a, b) => b.avgRating - a.avgRating);
setScores(scores);
});
}
Expand Down
23 changes: 7 additions & 16 deletions site/src/pages/SearchPage/ProfessorPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { FeaturedReviewData } from '@peterportal/types';

const ProfessorPopup: FC = () => {
const professor = useAppSelector(selectProfessor);
const [featured, setFeatured] = useState<FeaturedReviewData>(null!);
const [featured, setFeatured] = useState<FeaturedReviewData | undefined>();
const [scores, setScores] = useState<ScoreData[]>([]);

useEffect(() => {
Expand All @@ -18,31 +18,22 @@ const ProfessorPopup: FC = () => {
type: 'professor',
id: professor.ucinetid,
} as const;
trpc.reviews.scores.query(reviewParams).then((res: ScoreData[]) => {
trpc.reviews.avgRating.query(reviewParams).then((res) => {
const scores = res.map((course) => ({ name: course.name, avgRating: course.avgRating, id: course.name }));
const scoredCourses = new Set(res.map((v) => v.name));
res.forEach((v) => (v.key = v.name));
Object.keys(professor.courses).forEach((course) => {
// remove spaces
course = course.replace(/\s+/g, '');
// add unknown score
if (!scoredCourses.has(course)) {
res.push({ name: course, score: -1, key: course });
scores.push({ name: course, avgRating: -1, id: course });
}
});
// sort by highest score
res.sort((a, b) => b.score - a.score);
setScores(res);
});
trpc.reviews.featured.query(reviewParams).then((res) => {
// if has a featured review
if (res) {
setFeatured(res);
}
// no reviews for this professor
else {
setFeatured(null!);
}
res.sort((a, b) => b.avgRating - a.avgRating);
setScores(scores);
});
trpc.reviews.featured.query(reviewParams).then(setFeatured);
}
}, [professor]);

Expand Down
5 changes: 3 additions & 2 deletions site/src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import {

export interface ScoreData {
name: string;
score: number;
key?: string;
avgRating: number;
/** course id or ucinetid */
id: string;
}

export type SearchIndex = 'courses' | 'professors';
Expand Down

0 comments on commit 5def90b

Please sign in to comment.