CatalogEducation & public sector ›Schools & education

Grade average calculator — with saved history

Most online grade-average calculators forget everything the moment you close the tab: you retype every grade from scratch, every time. Here every grade you log stays saved on your device — open the app, add today's grade, and the average updates itself without rewriting the history.

▶ Use this app

schoolgradesaverageweighted averagestudentsreport card

What it records

  • Subject (e.g. Mathematics)
  • Grade (e.g. 7.5)
  • Subject
  • Grade (e.g. 8)
  • Weight (e.g. 2)

How it works

This is a Reactive app: a plain text document that your browser turns into a working app — forms, live data, tables, statistics and even charts, with nothing to install or configure.

  1. Use it right away. Hit “Use this app”: it opens right in your browser, ready to go, with data saved only on your device.
  2. Your data stays yours. Everything is stored locally on your device, kept separate for each app: no account, no server, nothing to set up.
  3. Make it your own. The text below is the entire app: copy it, tweak fields, views and words, and your changes become interactive instantly.
  4. Share it as a file. An app is a simple file: save it, export it or share it with a link; and with encrypted collaboration several people edit the same data in real time.
The app’s source
# 📐 Grade average calculator

Most online grade-average calculators forget everything the moment you close
the tab: you retype every grade from scratch, every time. Here every grade you
log stays saved on your device — open the app, add today's grade, and the
average updates itself without rewriting the history.

*Built around the Italian school grading scale (marks out of ten), but works
with any numeric scale you use.*

## Log a grade

::::form{path="grades" id="fv"}
::input{form="fv" field="subject" placeholder="Subject (e.g. Mathematics)" required="true"}
::input{form="fv" field="grade" type="number" placeholder="Grade (e.g. 7.5)" required="true"}
::input{form="fv" field="date" type="date" legend="Date of the test"}
::add-form{form="fv" path="grades" label="Log grade"}
::::

:::table{path="grades" headers="Subject,Grade,Date" deletable="true" editform="fv"}
**{subject}** | {grade} | {date}
:::

**Simple average: :avg[m]{path="grades" field="grade"}** over :count[n]{path="grades"} grades logged.

## Weighted average (with test weights)

If your school weighs written tests and oral exams differently, use this
second table: add the weight of each grade too (e.g. 1 for an oral exam, 2 for
a written test), and the weighted average is calculated below.

::::form{path="weightedgrades" id="fvp"}
::input{form="fvp" field="subject" placeholder="Subject" required="true"}
::input{form="fvp" field="grade" type="number" placeholder="Grade (e.g. 8)" required="true"}
::input{form="fvp" field="weight" type="number" placeholder="Weight (e.g. 2)" required="true"}
::add-form{form="fvp" path="weightedgrades" label="Add weighted grade"}
::::

:::table{path="weightedgrades" headers="Subject,Grade,Weight" deletable="true" editform="fvp"}
{subject} | {grade} | {weight}
:::

:::python{data="weightedgrades"}
```
rows = data["weightedgrades"]
grades = [(float(r["grade"]), float(r["weight"])) for r in rows if r.get("grade") and r.get("weight")]
if grades:
    total_weight = sum(w for _, w in grades)
    weighted_avg = sum(g * w for g, w in grades) / total_weight
    print(f"Weighted average: {weighted_avg:.2f}")
else:
    print("Add at least one grade with its weight to calculate the weighted average.")
```
:::

Keep a single grade log for the whole school year: you can scan how a subject
is trending straight from the table, and the average is always ready before a
parent-teacher meeting or a grading period review.