Skip to main content

Gradebook

Gradebook grid with one row per student, Class Section and Lab Section columns, two assignment columns showing Max 100, a Skill #12 column marked with a lock icon, calculated skills columns, and a footer with Download Gradebook, Import Columns, and Add Column

Column Semantics

In the Pawtograder gradebook system, columns represent individual grade components that collectively form a student’s overall course performance. Each column is defined by a unique slug identifier, a human-readable name, and a maximum score, but their power lies in their flexibility for grade calculation and data sources. Columns can be:
  • Manually entered by instructors who directly input grades cell-by-cell (supporting both whole numbers and decimal values)
  • Imported from CSV files to bulk-load grades from external systems (with full metadata tracking of the import source and date)
  • Linked to programming assignments through the assignment reference system
Creating an assignment automatically creates a matching gradebook column, so grades flow from submission reviews into the gradebook without any setup. The column is named after the assignment, gets the slug assignment-<assignment-slug>, takes its maximum score from the assignment’s total points, starts unreleased, and gets the score expression assignments("<assignment-slug>"). You cannot edit that expression from the column editor. Expressions: The most flexible column type uses score expressions that reference other columns or assignments, building a dependency graph for calculated grades. Using MathJS syntax, you can write formulas like (mean(gradebook_columns("homework-*")) + mean(gradebook_columns("project-*"))) / 2 to compute weighted averages, drop lowest scores, or apply curve adjustments. Score expressions can define functions and use MathJS’s math and utility functions, except that import, createUnit, reviver, and resolve are blocked and the arithmetic and comparison operators are replaced with gradebook-aware versions. Any grade that is automatically calculated can also be manually overridden on a case-by-case basis.

Student Visibility of Grades

The “released” status in the gradebook determines whether students can see a particular column and its grades. For imported or manually-entered columns, instructors have direct control over this visibility — they can release columns to make them visible to students or unrelease them to hide grades during grading periods or for sensitive assessments. This setting is at the column level only (you can’t release or unrelease individual grades). For columns that are automatically calculated by Pawtograder (via an expression), students always see the current calculation based only on what they can see. For example, a column defined as the average of all homeworks shows each student the average of the homework columns you have released to them.

Staff-Only Columns

When creating or editing a column, you can check Staff-only column (hidden from students until you release it). These columns are hidden from students until you release them. While unreleased, students cannot see the column definition or their grades. When you release a staff-only column, Pawtograder does two things in a single transaction: it copies the current private scores into the students’ public rows, and it clears the staff-only flag so the column behaves like a normal column from then on.
Releasing a staff-only column cannot be undone. Pawtograder asks you to confirm first. Because the release clears the staff-only flag, a calculated column loses its Release Column and Unrelease Column menu items afterwards: those items only appear for manually-entered columns and for staff-only columns.
Release is blocked while any cell in the column is still recalculating. If you try, you get a “Column is recalculating” error and nothing changes; wait and retry. Unreleasing a column clears the students’ public score, but only for manually-entered columns and for columns still marked staff-only. Unreleasing a released calculated column does not clear anything. Staff-only columns are useful for internal grading calculations, curve adjustments, bonus calculations, or draft grade formulas you want to finalize before sharing with students.

Automatic Recalculation of Dependent Columns

When you release or unrelease a gradebook column, Pawtograder automatically enqueues recalculation for all columns that depend on it. This ensures that calculated columns (those using expressions) always reflect the current visibility state and scores of their source columns. For example, if you have a “Final Grade” column that references “Homework Average,” releasing the homework average will trigger the final grade to recalculate for all students, ensuring they see accurate totals based on what’s now visible to them.

Managing Columns

Reordering Columns

You can reorder gradebook columns to organize them logically:
  • Drag and drop: Click and drag the grip handle in any column header to reorder columns
  • Move left/right: Open the column menu (the chevron in the column header) and select Move Left or Move Right to shift a column one position
  • Auto-layout: Click the Auto-layout columns button (grid icon) in the toolbar. Auto-layout first sorts every column by slug using a natural alphanumeric sort, so lab-2 comes before lab-10. It then makes a second pass that moves each calculated column after the columns it depends on, so dependencies always appear to the left of the columns that use them.
Column reordering is saved immediately and affects the display for all instructors and the export order in CSV files.

The Column Menu

The chevron in each column header opens a menu with:
  • Show Filter / Hide Filter: toggle the per-column filter input
  • Sort Ascending, Sort Descending, Clear Sort
  • Edit Column: open the column editor (name, maximum score, score expression, render expression, and staff-only)
  • Move Left, Move Right
  • Release Column, Unrelease Column: shown only for manually-entered columns and for staff-only columns
  • Convert Missing to 0: shown only for manually-entered columns and for columns whose score expression starts with assignments(
  • Delete Column
Column and section filter dropdowns carry Select all and Select none buttons for faster multi-select filtering.

Manual Grade Entry

You can manually enter or edit grades directly in the gradebook by clicking on any cell. The gradebook accepts both whole numbers and decimal values, so you can enter grades like 8.5 or 92.75. This is useful for assignments with partial credit or weighted scoring.
Pawtograder does not check entered scores against the column’s maximum score. A score above the maximum is accepted and stored as-is.
The cell editor also carries three per-grade flags:
  • Droppable: this grade is eligible to be dropped by drop_lowest
  • Excused: the student is excused from this item
  • Missing: the grade has not been entered (see below)
For a calculated or imported column, the editor switches to override mode. It shows the current calculated value, an override field, and a Note field where you can record why you overrode it. Overrides persist through recalculation and re-import. For calculated columns, both other staff and the student see that the score was overridden from the calculated value; for imported columns, staff see the override but students do not. A Reset button next to Override clears the override and restores the calculated value.

Missing Grades

Missing is a distinct state from a score of 0. A missing grade does not count as a zero: a calculated column that depends on one is marked “not final” rather than silently computing a lower score. When you have finished grading an item and want the missing entries to count as zeros, open the column menu and choose Convert Missing to 0. This sets score = 0, clears the missing flag, and stamps the note Missing value converted to 0 on every affected grade in the column. It cannot be undone, and it is only offered for manually-entered columns and for columns whose score expression starts with assignments(.

Gradebook Recalculation

When gradebook columns use expressions that reference other columns, Pawtograder automatically recalculates affected grades when dependencies change. This recalculation process runs asynchronously in the background to maintain performance for large courses.
  • When a grade changes, the system enqueues a recalculation job for each affected gradebook row and marks that row dirty and recalculating.
  • Each enqueue also bumps a per-row version counter, which invalidates any worker already computing that row.
  • A background worker takes each job, computes the row, and writes the result back only if nothing has changed in the meantime. A result computed from inputs that have since moved is discarded rather than overwriting the fresher value.
  • Mismatched rows are re-enqueued with an attempt counter and exponential backoff. Past a retry ceiling the row goes to a dead letter queue instead of cycling forever.
The result is that calculated grades stay current even during heavy activity, such as several graders entering scores at once, without one worker clobbering another’s results.

”What If” Grade Calculations

What-If is a student-facing mode that lets students explore hypothetical grade scenarios by temporarily adjusting their own scores. It answers questions like “What grade do I need on the final exam to get an A?” or “How will my grade change if I skip this assignment?” When a student uses What-If:
  • They can click any grade card that is not itself calculated from other gradebook columns and type a hypothetical score. Columns that depend on other columns are read-only, since those are the ones What-If recomputes.
  • Calculated columns update immediately to reflect the hypothetical scenario.
  • All changes are temporary and client-side only. No actual grades are modified.
  • Simulated cards are highlighted with an info background so they stand out from real grades.
  • To undo a simulation, clear the input for that grade. There is no bulk reset control.
  • A grade that has a staff override is never replaced by a simulation.
You enable What-If for students under Course Settings → Feature flags (“Student gradebook What-If”). It is off by default. When disabled, the student gradebook is view-only and shows a banner saying so.
What-If does not apply to the staff gradebook. The instructor view renders the same student grade components read-only, so there is no staff-side scenario modeling.

Importing Grades

To import grades, instructors use a 3-step wizard:
  1. File Selection: Click the Import Columns button and select a CSV file from your computer, which the system parses client-side to extract tabular data.
  2. Column Mapping: Choose which CSV column contains student identifiers and select whether they are email addresses or student IDs. For each remaining CSV column, decide whether to map it to an existing gradebook column for updates, create a new column (requiring you to set the maximum score), or ignore the column entirely. The system automatically detects email columns if present.
  3. Preview & Confirm: Review a comprehensive preview table that shows exactly what changes will occur, highlighting grade updates with strikethrough old values and bold new values, warning about students in the CSV who aren’t enrolled in the course, and providing alerts when attempting to override calculated column scores. Only after reviewing this detailed preview can you click Confirm Import to execute the changes.
The system automatically creates new columns with full audit metadata including filename, date, and creator information, updates only enrolled students’ grades while preserving override behavior for calculated columns, and maintains complete import history for traceability and compliance purposes.

Expression Builder

When creating or editing a column with a score expression, Pawtograder provides an Expression Builder interface with live validation and debugging tools:
  • Live validation: As you type, the expression is parsed and validated in real-time. Parse errors and dependency errors (unknown column slugs, cycles) are shown immediately.
  • Full-screen mode: Click Expression Builder to expand to a full-screen Monaco editor with additional features:
    • Syntax highlighting and autocomplete: The editor provides syntax highlighting for the gradebook expression language, with autocomplete for built-in functions and column slugs. Typing inside gradebook_columns("…") shows matching column slugs from your gradebook.
    • Hover documentation: Hover over any sub-expression to see its current evaluated value for the selected student.
    • Student picker: Select a student to test the expression against their actual gradebook data.
    • Per-line evaluation: See the intermediate value of each statement in your expression, displayed as inline annotations (e.g. = 42) next to each line.
    • Result badges: A Score badge shows the numeric result, and a Rendered badge shows the rendered form when a render expression is set.
    • Incomplete dependencies: A panel listing which dependency slugs are Missing and which are Not released for the selected student.
  • Save blocking: The Save button is disabled while the expression fails to parse, references an unknown column slug, or would create a cycle. An evaluation error for the selected student does not block saving.
The Expression Builder helps you write and debug complex expressions before saving them, ensuring they work correctly for all students.

Expression Syntax

The gradebook expression system is built on MathJS, with added functions for grade calculations. The value of the last line is the student’s score for that column. If that value is undefined or null, the score is stored as null rather than as 0. Comments start with #. MathJS has no // comment syntax, so a // comment is a parse error.

Core Syntax

Expressions follow standard mathematical notation with variables, operators, and functions:
Every gradebook has an optional expression prefix. Pawtograder prepends it, followed by a newline, to every score expression and every render expression in that gradebook before evaluating. Use it for shared helper function definitions and constants you do not want to repeat in each column. There is no screen for editing it, so setting one takes a Pawtograder administrator.

Data Access Functions

gradebook_columns("slug-pattern")

Retrieves gradebook column data for the student being calculated. With a single slug it returns one object; with a pattern containing * it returns an array of objects, one per matching column. The object carries the student’s whole grade record for that column, plus computed fields. The ones you will use:
  • score: number | null - The student’s score, with any override already applied
  • max_score: number - The maximum score for the column
  • is_missing: boolean - Whether the grade is missing or not yet entered
  • is_excused: boolean - Whether the student is excused from this item
  • is_droppable: boolean - Whether drop_lowest may drop this item
  • is_private: boolean - Whether this is the staff-visible row or the student-visible row
  • column_slug: string - The slug of the source column
  • released: boolean - Whether the column is released to the student
  • score_override, score_override_note, is_recalculating, incomplete_values, id
Only * expands a pattern into an array. Dependency validation in the editor uses full glob matching, so a pattern like hw-0? resolves and saves without complaint, but at evaluation time it is treated as one literal slug and matches nothing.

assignments("assignment-slug"[, "review-round"])

Returns the student’s total score for one review round on the assignment, not the assignment’s point value. The second argument selects the round and defaults to "grading-review". The valid rounds are self-review, grading-review, meta-grading-review, and code-walk. As with gradebook_columns, a slug containing * returns an array. Unlike gradebook_columns, the values are plain numbers rather than objects, so they work with sum but not with mean or drop_lowest, both of which need a max_score per entry.

Array Processing Functions

countif(array, predicate)

Counts array elements matching a condition using lambda syntax. Returns undefined for an empty array.

sum(array)

Sums numeric values or the scores of gradebook objects, skipping null and undefined entries. Returns undefined for an empty array. A gradebook object with a null score contributes 0.

mean(array, weighted)

Calculates a weighted or unweighted average. weighted is a positional second argument that defaults to true; there are no named arguments in MathJS.
Weighted average is defined as:
Unweighted average is defined as:
Grades marked is_missing count as 0 points, unless they are also marked is_excused, in which case they are excluded from the average. Marking a grade excused on its own does not exclude it; the grade must be both missing and excused. mean also silently drops entries it cannot average: undefined and null array entries, entries whose max_score is missing, null, or not greater than zero, and entries whose score is null while is_missing is false. If nothing is left, mean returns undefined.
mean returns a percentage on a 0-100 scale, not a raw point total. If your column’s maximum score is 100, the two happen to coincide; otherwise they do not.

drop_lowest(array, count)

Returns the array with up to count of the lowest items removed.
Ranking is by percentage (score / max_score), not by raw score. Given a 10-point quiz scored 6/10 and a 100-point exam scored 70/100, the quiz ranks lower and is dropped first, even though 6 is the smaller number. Only grades with the droppable flag set are eligible to be dropped, which is the default for new grades.
drop_lowest also removes every entry whose score is null or whose max_score is not greater than zero. Those removals happen regardless of the droppable flag and do not count against count, so ungraded items disappear from the array before any dropping occurs.

min(...) and max(...)

min and max accept any mix of numbers, gradebook objects, and arrays, flatten them, and use each gradebook object’s score. Entries that are null or undefined are skipped. With no usable values left, both return undefined.
Several functions return undefined rather than 0 when they have nothing to work with: sum and countif on an empty array, mean with no averageable entries, min and max with no values, and case_when with no matching row. If that undefined reaches the last line of the expression, the column’s score is stored as null, and the cell renders as -.

Conditional Logic

case_when([condition, value; ...])

Convenience function for multi-condition branching using matrix syntax:
Rows are tested top to bottom and the first matching row’s value is returned. If no row matches, case_when returns undefined, which stores as a null score. Include a true row as a default.

Comparison Functions

==, !=, >, >=, <, and <= are available and are replaced with gradebook-aware versions. They return 1 or 0, not true or false. That is what makes them work inside case_when matrices, and/or chains, and arithmetic.
Each comparison coerces only its left operand from a gradebook object to a score. Write gradebook_columns("hw-01") >= 85, not 85 <= gradebook_columns("hw-01"). The reversed form compares a number against an object and is always 0.

Complete Examples

Simple Counting Example

Complex Grade Calculation

Render Expressions

A render expression controls how a column’s score is displayed. It does not change the stored score. Set it in the Render Expression field of the column editor, next to the score expression. A render expression sees exactly two variables:
  • score: the stored score, with any override already applied
  • max_score: the column’s maximum score
With no render expression set, Pawtograder uses round(score, 2). The gradebook’s expression prefix is prepended to render expressions too, so helpers defined there are available here. As with score expressions, import, createUnit, reviver, and resolve are blocked. If the expression produces multiple statements, only the last one is displayed. Two states bypass the expression entirely: a grade flagged Missing renders as Missing, and a grade with no score at all renders as -.

Built-In Display Helpers

letter uses fixed breakpoints: 93 A, 90 A-, 87 B+, 83 B, 80 B-, 77 C+, 73 C, 70 C-, 67 D+, 63 D, 60 D-, and F below 60. You cannot change them; use customLabel for a different scale. All three of letter, check, and checkOrX return (N/A) when score is undefined.
customLabel returns the value from the first row whose threshold the input meets or exceeds, so list thresholds from highest to lowest. If no row matches, it returns the literal string Error.

Exporting Grades

You can export gradebook data to CSV for external analysis or record-keeping. The export is built in the browser from data already loaded, so it downloads immediately.

How to Export

  1. Click the Download Gradebook button at the bottom of the gradebook page
  2. Optionally check Use render expressions in CSV
  3. Click Download CSV

Export Options

Both options export the same set of students and columns; they differ only in how each cell is formatted.
  1. Default: every cell is the stored numeric score, with any manual override applied. Score expressions are never exported; only their results.
  2. Use render expressions in CSV: for columns that have a render expression, the cell holds the rendered string that the gradebook displays, such as A or ✔️, rather than a number. Columns without a render expression still export their numeric score.
The rendered export produces text, not numbers. Pick it when you want a human-readable transcript; leave it unchecked when the file feeds a spreadsheet formula or another grading system.

Export Contents

The first row is a header: Name, Email, SID, Course Section, Lab Section, Tags, then one column per gradebook column, in the gradebook’s display order. One row follows per enrolled student. Students who have dropped the course are skipped. The file is written with a UTF-8 byte-order mark so Excel opens it as UTF-8 instead of mangling non-ASCII characters. Every cell is quoted with internal quotes doubled, and any cell starting with =, +, @, or - is prefixed with an apostrophe to prevent spreadsheet formula injection.