Skip to content
This repository has been archived by the owner on Oct 18, 2024. It is now read-only.

Commit

Permalink
chore: 🔧 merge main into fourmilier
Browse files Browse the repository at this point in the history
  • Loading branch information
ecxyzzy committed Oct 15, 2023
2 parents f7f7db9 + 7d9ab02 commit fcc1186
Show file tree
Hide file tree
Showing 16 changed files with 716 additions and 62 deletions.
36 changes: 21 additions & 15 deletions apps/api/src/routes/v1/graphql/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,26 @@ import { geTransform, proxyRestApi } from "./lib";

export const resolvers: ApolloServerOptions<BaseContext>["resolvers"] = {
Query: {
calendar: proxyRestApi("/v1/rest/calendar"),
course: proxyRestApi("/v1/rest/courses", { pathArg: "courseId" }),
courses: proxyRestApi("/v1/rest/courses", { argsTransform: geTransform }),
allCourses: proxyRestApi("/v1/rest/courses/all"),
rawGrades: proxyRestApi("/v1/rest/grades/raw"),
aggregateGrades: proxyRestApi("/v1/rest/grades/aggregate"),
gradesOptions: proxyRestApi("/v1/rest/grades/options"),
instructor: proxyRestApi("/v1/rest/instructors", { pathArg: "courseId" }),
instructors: proxyRestApi("/v1/rest/instructors"),
allInstructors: proxyRestApi("/v1/rest/instructors/all"),
larc: proxyRestApi("/v1/rest/larc"),
websoc: proxyRestApi("/v1/rest/websoc", { argsTransform: geTransform }),
depts: proxyRestApi("/v1/rest/websoc/depts"),
terms: proxyRestApi("/v1/rest/websoc/terms"),
week: proxyRestApi("/v1/rest/week"),
calendar: proxyRestApi("v1/rest/calendar"),
course: proxyRestApi("v1/rest/courses", { pathArg: "courseId" }),
courses: proxyRestApi("v1/rest/courses", { argsTransform: geTransform }),
allCourses: proxyRestApi("v1/rest/courses/all"),
rawGrades: proxyRestApi("v1/rest/grades/raw"),
aggregateGrades: proxyRestApi("v1/rest/grades/aggregate"),
gradesOptions: proxyRestApi("v1/rest/grades/options"),
aggregateByCourse: proxyRestApi("v1/rest/grades/aggregateByCourse", {
argsTransform: geTransform,
}),
aggregateByOffering: proxyRestApi("v1/rest/grades/aggregateByOffering", {
argsTransform: geTransform,
}),
instructor: proxyRestApi("v1/rest/instructors", { pathArg: "ucinetid" }),
instructors: proxyRestApi("v1/rest/instructors"),
allInstructors: proxyRestApi("v1/rest/instructors/all"),
larc: proxyRestApi("v1/rest/larc"),
websoc: proxyRestApi("v1/rest/websoc", { argsTransform: geTransform }),
depts: proxyRestApi("v1/rest/websoc/depts"),
terms: proxyRestApi("v1/rest/websoc/terms"),
week: proxyRestApi("v1/rest/week"),
},
};
1 change: 1 addition & 0 deletions apps/api/src/routes/v1/graphql/schema/enum.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ enum Quarter {
}
"The set of valid GE category codes."
enum GE {
ANY
GE_1A
GE_1B
GE_2
Expand Down
85 changes: 85 additions & 0 deletions apps/api/src/routes/v1/graphql/schema/grades.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ type GradesSection {
courseNumber: String!
"The numeric part of the course number."
courseNumeric: Int!
"What GE categor(y/ies) this section satisfies (if any)."
geCategories: [GE!]!
"The shortened name(s) of the instructor(s) who taught the section."
instructors: [String!]!
}
Expand Down Expand Up @@ -50,6 +52,8 @@ type RawGrade {
courseNumber: String!
"The numeric part of the course number."
courseNumeric: Int!
"What GE categor(y/ies) this section satisfies (if any)."
geCategories: [GE!]!
"How many students attained an A+/A/A-."
gradeACount: Int!
"How many students attained a B+/B/B-."
Expand Down Expand Up @@ -91,6 +95,58 @@ type GradesOptions {
"The list of instructors that matched the given filters."
instructors: [String!]!
}
"An object that represents aggregate grades statistics for a course taught by an instructor."
type AggregateGradeByCourse {
"The department code."
department: String!
"The course number the section belongs to."
courseNumber: String!
"How many students attained an A+/A/A-."
gradeACount: Int!
"How many students attained a B+/B/B-."
gradeBCount: Int!
"How many students attained a C+/C/C-."
gradeCCount: Int!
"How many students attained a D+/D/D-."
gradeDCount: Int!
"How many students attained an F."
gradeFCount: Int!
"How many students attained a P."
gradePCount: Int!
"How many students attained an NP."
gradeNPCount: Int!
"How many students attained a W."
gradeWCount: Int!
"The average GPA of all assigned grades in the course."
averageGPA: Float!
}
"An object that represents aggregate grades statistics for a course taught by an instructor."
type AggregateGradeByOffering {
"The department code."
department: String!
"The course number the section belongs to."
courseNumber: String!
"The shortened name of the instructor who taught the section."
instructor: String!
"How many students attained an A+/A/A-."
gradeACount: Int!
"How many students attained a B+/B/B-."
gradeBCount: Int!
"How many students attained a C+/C/C-."
gradeCCount: Int!
"How many students attained a D+/D/D-."
gradeDCount: Int!
"How many students attained an F."
gradeFCount: Int!
"How many students attained a P."
gradePCount: Int!
"How many students attained an NP."
gradeNPCount: Int!
"How many students attained a W."
gradeWCount: Int!
"The average GPA of all assigned grades in the course."
averageGPA: Float!
}

extend type Query {
"Get the raw grade info for the given parameters."
Expand All @@ -113,6 +169,7 @@ extend type Query {
courseNumber: String
sectionCode: String
division: Division
ge: GE
excludePNP: Boolean
): AggregateGrades!
"Get the available options for the given constraints."
Expand All @@ -124,6 +181,34 @@ extend type Query {
courseNumber: String
sectionCode: String
division: Division
ge: GE
excludePNP: Boolean
): GradesOptions!
"Get the aggregate grade info, grouped by course, for the given parameters."
aggregateByCourse(
year: String
quarter: Quarter
instructor: String
department: String
courseNumber: String
sectionCode: String
division: Division
ge: GE
excludePNP: Boolean
): [AggregateGradeByCourse!]!
"""
Get the aggregate grade info, grouped by offering (course and instructor),
for the given parameters.
"""
aggregateByOffering(
year: String
quarter: Quarter
instructor: String
department: String
courseNumber: String
sectionCode: String
division: Division
ge: GE
excludePNP: Boolean
): [AggregateGradeByOffering!]!
}
57 changes: 46 additions & 11 deletions apps/api/src/routes/v1/rest/grades/{id}/+endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import { PrismaClient } from "@libs/db";
import { createErrorResult, createOKResult, logger } from "@libs/lambda";
import type { GradesOptions, GradesRaw } from "@peterportal-api/types";
import type {
AggregateGradesByCourse,
AggregateGradesByOffering,
GradesOptions,
RawGrades,
} from "@peterportal-api/types";
import type { APIGatewayProxyHandler } from "aws-lambda";
import { ZodError } from "zod";

import { aggregateGrades, constructPrismaQuery, lexOrd } from "./lib";
import {
aggregateGrades,
aggregateByOffering,
constructPrismaQuery,
lexOrd,
transformRow,
aggregateByCourse,
} from "./lib";
import { QuerySchema } from "./schema";

const prisma = new PrismaClient();

export const GET: APIGatewayProxyHandler = async (event, context) => {
const headers = event.headers;
const params = event.pathParameters;
const query = event.queryStringParameters;
const requestId = context.awsRequestId;
const { headers, pathParameters: params, queryStringParameters: query } = event;
const { awsRequestId: requestId } = context;

/**
* TODO: handle warmer requests.
Expand All @@ -39,13 +49,10 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
where: constructPrismaQuery(parsedQuery),
include: { instructors: true },
})
).map((section) => ({
...section,
instructors: section.instructors.map((instructor) => instructor.name),
}));
).map(transformRow);
switch (params.id) {
case "raw":
return createOKResult<GradesRaw>(res, headers, requestId);
return createOKResult<RawGrades>(res, headers, requestId);
case "aggregate":
return createOKResult(aggregateGrades(res), headers, requestId);
}
Expand Down Expand Up @@ -103,6 +110,34 @@ export const GET: APIGatewayProxyHandler = async (event, context) => {
requestId,
);
}
case "aggregateByCourse": {
return createOKResult<AggregateGradesByCourse>(
aggregateByCourse(
(
await prisma.gradesSection.findMany({
where: constructPrismaQuery(parsedQuery),
include: { instructors: true },
})
).map(transformRow),
),
headers,
requestId,
);
}
case "aggregateByOffering": {
return createOKResult<AggregateGradesByOffering>(
aggregateByOffering(
(
await prisma.gradesSection.findMany({
where: constructPrismaQuery(parsedQuery),
include: { instructors: true },
})
).map(transformRow),
),
headers,
requestId,
);
}
}
return createErrorResult(
400,
Expand Down
Loading

0 comments on commit fcc1186

Please sign in to comment.