diff --git a/nextjs/src/models/local/assignment/utils/assignmentPointsUtils.ts b/nextjs/src/models/local/assignment/utils/assignmentPointsUtils.ts index 0e62446..17dd74c 100644 --- a/nextjs/src/models/local/assignment/utils/assignmentPointsUtils.ts +++ b/nextjs/src/models/local/assignment/utils/assignmentPointsUtils.ts @@ -5,6 +5,6 @@ export const assignmentPoints = (assignment: LocalAssignment) => { .map((r) => r.label.toLowerCase().includes("(extra credit)") ? 0 : r.points ) - .reduce((acc, current) => acc + current, 0); + .reduce((acc, current) => (current > 0 ? acc + current : acc), 0); return basePoints; }; diff --git a/nextjs/src/services/canvas/canvasAssignmentService.ts b/nextjs/src/services/canvas/canvasAssignmentService.ts index cce9f5d..5c6c4f2 100644 --- a/nextjs/src/services/canvas/canvasAssignmentService.ts +++ b/nextjs/src/services/canvas/canvasAssignmentService.ts @@ -8,7 +8,7 @@ import { assignmentPoints } from "@/models/local/assignment/utils/assignmentPoin import { getDateFromString } from "@/models/local/timeUtils"; import { canvasModuleService } from "./canvasModuleService"; import { CanvasModule } from "@/models/canvas/modules/canvasModule"; - +import { getRubricCriterion } from "./canvasRubricUtils"; export const canvasAssignmentService = { async getAll(courseId: number): Promise { @@ -25,7 +25,7 @@ export const canvasAssignmentService = { async create( canvasCourseId: number, localAssignment: LocalAssignment, - canvasAssignmentGroupId?: number, + canvasAssignmentGroupId?: number ) { console.log(`Creating assignment: ${localAssignment.name}`); const url = `${canvasApi}/courses/${canvasCourseId}/assignments`; @@ -108,22 +108,8 @@ const createRubric = async ( assignmentCanvasId: number, localAssignment: LocalAssignment ) => { - const criterion = localAssignment.rubric - .map((rubricItem) => ({ - description: rubricItem.label, - points: rubricItem.points, - ratings: { - 0: { description: "Full Marks", points: rubricItem.points }, - 1: { description: "No Marks", points: 0 }, - }, - })) - .reduce((acc, item, index) => { - return { - ...acc, - [index]: item, - }; - }, {} as { [key: number]: { description: string; points: number; ratings: { [key: number]: { description: string; points: number } } } }); - + const criterion = getRubricCriterion(localAssignment.rubric); + const rubricBody = { rubric_association_id: assignmentCanvasId, rubric: { diff --git a/nextjs/src/services/canvas/canvasRubricUtils.ts b/nextjs/src/services/canvas/canvasRubricUtils.ts new file mode 100644 index 0000000..b4a4cc8 --- /dev/null +++ b/nextjs/src/services/canvas/canvasRubricUtils.ts @@ -0,0 +1,22 @@ +import { RubricItem } from "@/models/local/assignment/rubricItem"; + +export const getRubricCriterion = (rubric: RubricItem[]) => { + const criterion = rubric + .map((rubricItem) => ({ + description: rubricItem.label, + points: rubricItem.points, + ratings: { + 0: { description: "Full Marks", points: rubricItem.points }, + 1: { description: "No Marks", points: 0 }, + }, + })) + .reduce((acc, item, index) => { + return { + ...acc, + [index]: item, + }; + }, {} as { [key: number]: { description: string; points: number; ratings: { [key: number]: { description: string; points: number } } } }); + + return criterion + +} \ No newline at end of file diff --git a/nextjs/src/services/canvas/rubric.test.ts b/nextjs/src/services/canvas/rubric.test.ts new file mode 100644 index 0000000..bb80e31 --- /dev/null +++ b/nextjs/src/services/canvas/rubric.test.ts @@ -0,0 +1,72 @@ +import { RubricItem } from "@/models/local/assignment/rubricItem"; +import { describe, expect, it } from "vitest"; +import { getRubricCriterion } from "./canvasRubricUtils"; + +describe("can prepare rubric for canvas", () =>{ + it("can parse normal rubric into criterion", () =>{ + const rubric: RubricItem[] = [ + { + label: "first", + points: 1 + }, + { + label: "second", + points: 2 + }, + ] + const criterion = getRubricCriterion(rubric) + + expect(criterion).toStrictEqual({ + 0: { + description: "first", + points: 1, + ratings: { + 0: { description: "Full Marks", points: 1 }, + 1: { description: "No Marks", points: 0 }, + } + }, + 1: { + description: "second", + points: 2, + ratings: { + 0: { description: "Full Marks", points: 2 }, + 1: { description: "No Marks", points: 0 }, + } + } + }) + }) + + + it("can parse negative rubric into criterion", () =>{ + const rubric: RubricItem[] = [ + { + label: "first", + points: 1 + }, + { + label: "second", + points: -2 + }, + ] + const criterion = getRubricCriterion(rubric) + + expect(criterion).toStrictEqual({ + 0: { + description: "first", + points: 1, + ratings: { + 0: { description: "Full Marks", points: 1 }, + 1: { description: "No Marks", points: 0 }, + } + }, + 1: { + description: "second", + points: -2, + ratings: { + 0: { description: "Full Marks", points: -2 }, + 1: { description: "No Marks", points: 0 }, + } + } + }) + }) +}) \ No newline at end of file diff --git a/requests/assignment.http b/requests/assignment.http index 5e92ddf..0d27ba0 100644 --- a/requests/assignment.http +++ b/requests/assignment.http @@ -157,5 +157,15 @@ Content-Type: application/json "name": "test module" } } +### +POST https://snow.instructure.com/api/v1/courses/courses/960410/rubrics/1961869 +Authorization: Bearer {{$dotenv CANVAS_TOKEN}} +Content-Type: application/json + +{ + "module": { + "name": "test module" + } +}