Possible final grade range
The possible final grade range calculator shows how much room remains in a course before every assignment has been graded.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
Enter each completed score with its weight, then provide the combined weight of all unfinished work. The result gives your current weighted average and the worst and best final grades still reachable if the remaining work earns the minimum or maximum allowed score. It works with percentage weights, decimal weights, or point-style weights, provided every weight uses the same scale.
Describe the completed and unfinished parts of the course
Start by entering every completed piece of coursework as a score and a weight. A midterm worth 25 percent can use a weight of 25, while a quiz worth 5 percent can use 5. If your syllabus uses decimal shares, 0.25 and 0.05 work equally well. What matters is consistency: do not mix percentages, decimals, and raw points in the same request. Then enter the combined weight of all unfinished assignments. You do not need to predict individual remaining scores because this calculator is finding the outer limits, not a single forecast. By default, the lowest possible score is 0 and the highest is 100. You can change those bounds for courses with a different grading scale, guaranteed participation credit, capped assessments, or extra-credit rules. Completed scores must fall inside the same bounds, which catches common data-entry mistakes before a plausible-looking but misleading range is returned. The total declared weight is the sum of completed and remaining weight, so the calculation also works when the syllabus uses weights that do not literally add to 100.
Understand how the reachable range is calculated
Each completed score is multiplied by its weight, and those products are added to form the earned contribution so far. The current average divides that contribution by completed weight only, which describes performance on work already graded. The final range uses a different denominator: completed weight plus unfinished weight. For the worst reachable final grade, all remaining weight is assigned the minimum allowed score. For the best reachable final grade, it is assigned the maximum allowed score. These are mathematical endpoints, not predictions about likely performance. If half of the course remains, the interval may be wide even when the current average is stable. If only a small project remains, the interval will usually be narrow. Rounding is applied only to the reported values, after the weighted calculations, and you can request from zero to six decimal places. Because the same score bounds apply across completed and unfinished work, the output stays easy to interpret on conventional 0–100 scales as well as custom scales such as 0–20 or 1–10.
Use the result for planning without overreading it
Treat the worst and best values as boundary markers for planning. If a desired course grade lies above the best reachable value, even perfect scores on all remaining work cannot reach it under the weights supplied. If a threshold lies at or below the worst value, that outcome is already secured even at the minimum remaining score. When a target falls inside the interval, it is still possible, but this calculator does not say what average you must earn to hit that target; it only shows the full feasible span. Check the syllabus before acting on the result. Dropped assignments, category normalization, curved grades, replacement exams, penalties, extra credit, and weights that change after exemptions can all alter the effective calculation. Combine unfinished assignments into one remaining weight only when they share the same permitted score range. If one assessment has a special cap or guaranteed floor, calculate separate scenarios with appropriate bounds. Saving the input alongside the result makes it easier to update the range after the next grade arrives and to explain exactly which assumptions produced it.
What you can do with it
Check whether a target is still possible
Compare a desired course grade with the best final grade reachable if all unfinished work receives the maximum score.
See whether a threshold is secured
Compare a pass, scholarship, or prerequisite threshold with the worst reachable final grade under the stated minimum score.
Update plans after each posted grade
Move newly graded work into the completed list, reduce remaining weight, and watch the possible interval narrow.
FAQ
What does the calculation cost?
It is free to run in the browser. API requests cost $0.002.
Do the weights have to add to 100?
No. They can be percentages, decimal shares, or another consistent positive scale because the result is normalized by total declared weight.
Why is the current average different from the final range?
The current average uses only completed weight, while both final endpoints include completed and unfinished weight in the denominator.
Can I use a grading scale other than 0 to 100?
Yes. Set min_score and max_score to the endpoints of your scale, and express every completed score on that same scale.
Does the best grade predict what I will earn?
No. It is the mathematical maximum under the supplied weights and score bounds, not a forecast or probability.
How should I handle extra credit or dropped grades?
Model only the effective weights and bounds defined by the course policy. Run multiple scenarios when the policy changes which work counts.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/edu/grade-range-remaining \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"completed":[{"score":82,"weight":20},{"score":91,"weight":30}],"remaining_weight":50}'const res = await fetch("https://api.kit.forhosting.com/edu/grade-range-remaining", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"completed": [
{
"score": 82,
"weight": 20
},
{
"score": 91,
"weight": 30
}
],
"remaining_weight": 50
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/edu/grade-range-remaining",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"completed": [
{
"score": 82,
"weight": 20
},
{
"score": 91,
"weight": 30
}
],
"remaining_weight": 50
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/edu/grade-range-remaining", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"completed":[{"score":82,"weight":20},{"score":91,"weight":30}],"remaining_weight":50}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"completed":[{"score":82,"weight":20},{"score":91,"weight":30}],"remaining_weight":50}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/edu/grade-range-remaining", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"completed": [
{
"score": 82,
"weight": 20
},
{
"score": 91,
"weight": 30
}
],
"remaining_weight": 50
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "edu.grade_range_remaining",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_items | 100 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |