Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,82 @@

Repository for team IT2810-H26-T29 in IT2810-H26.

We are building a web application that helps gymnastics coaches plan their gymnasts' routines. It contains a searchable catalog of all elements and vaults in the FIG Women's Artistic Gymnastics Code of Points 2025–2028. Coaches can put together routines for their gymnasts and see the D-value (difficulty value) of each routine.

## Status

The first delivery is a specification. There is no working application yet.

The code in `src/` is the Vite starter project with one example test. The tooling is set up: TypeScript, ESLint, Prettier and Vitest.

## What to review

| Document | Describes |
| ---------------------------------------- | ---------------------------------------------------------------------------------------- |
| [docs/UI_PLANS.md](docs/UI_PLANS.md) | The user groups, user stories and pages of the application |
| [docs/DATA_MODEL.md](docs/DATA_MODEL.md) | The entities, how they relate, the constraints and the reasoning behind the main choices |
| [docs/examples/](docs/examples/) | Invented example data that shows how each entity in the data model is structured |
| [docs/AI_USAGE.md](docs/AI_USAGE.md) | How AI was used in the project |

## The dataset

The catalog data comes from the FIG Women's Artistic Gymnastics Code of Points 2025–2028, which is published as a PDF. We will extract the apparatus, element groups, elements and vaults from the PDF with a script, and load them into the database with a seed script. Neither script is written yet.

The data is used for educational purposes. All rights to the Code of Points belong to FIG (Fédération Internationale de Gymnastique).

## Planned functionality

For everyone, without logging in:

- Search, filter and sort all elements and vaults
- See the details of one element or vault: code, value, description, image and variants
- Put together a routine in the calculator and see its D-value

For coaches, who log in with Google:

- Create gymnast profiles
- Build and save routines for each gymnast, with several routines per apparatus
- Keep a list of the elements each gymnast can do or is practicing

The D-value of a routine is calculated from its elements and is not stored. Composition requirements and connection values are not included in this version.

## Technology

In the repository now:

- React, TypeScript and Vite for the frontend
- ESLint and Prettier for linting and formatting
- Vitest for testing

Planned:

- A GraphQL backend in Node and TypeScript
- A database installed directly on the VM.

## Getting started

> **Not relevant yet.** The first delivery is a specification, so you do not need to run anything to review it. These commands only start the starter project.
You need Node 24 (see `.nvmrc`) and pnpm. If you have npm but not pnpm, install it with `npm install -g pnpm`.

```bash
nvm use
pnpm install
pnpm dev
```

`pnpm dev` starts the starter project at http://localhost:5173.

Other commands:

| Command | What it does |
| -------------- | ----------------------------------------------- |
| `pnpm build` | Type-checks and builds the project into `dist/` |
| `pnpm preview` | Serves the built project locally |
| `pnpm lint` | Runs ESLint |
| `pnpm format` | Formats all files with Prettier |
| `pnpm test` | Runs the tests with Vitest |

## Working in this repository

`main` is protected — you cannot push to it directly. Work on a branch and
Expand Down
36 changes: 36 additions & 0 deletions docs/AI_USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,39 @@
- **What Claude did:** Wrote the Mermaid code for the ER diagram and drafted
the descriptions, based on our conversation.
- **Review:** The team reviewed the result and edited it.

## Example data (`docs/examples/`)

- **Tool:** Claude Code
- **What the team did:** Wrote the task description: which files to create,
what each should contain, and that the data must follow the constraints in
the data model.
- **What Claude did:** Generated all the data in the JSON files and wrote the
README. The elements, vaults, descriptions, names, coach, gymnasts and
routines are invented by Claude. The apparatus and element group names were
written by Claude from its knowledge of the Code of Points, not copied from
the document. Claude also checked with a script that all referenced ids
exist and that the data follows the constraints.
- **Prompt:**

```text
Add example JSON files in docs/examples/ that show how the data in docs/DATA_MODEL.md is
structured. They are documentation only, and the catalog entries are invented.
Files (JSON arrays):
- apparatus.json and elementGroups.json: all 4 apparatus and all 22 groups, with real names
from the Code of Points table of contents.
- elements.json: 2–3 per UB, BB and FX. At least one named element and one element with
two variants.
- vaults.json: two vaults from different groups.
- variantGroups.json: one group for the element with variants.
- coaches.json, gymnasts.json, routines.json: one coach, two gymnasts, and routines that include
two routines on the same apparatus and one vault routine.
Invented entries must look plausible: codes and values follow the Code of Points pattern
("3.304" = group 3, C, 0.3), but don't copy real descriptions.
Check that all referenced ids exist and that the data follows the constraints in DATA_MODEL.md.
Add a short README in docs/examples/ saying the data is invented, and link to the folder from
DATA_MODEL.md.
```
2 changes: 2 additions & 0 deletions docs/DATA_MODEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ This document describes the data model for the Code of Points catalog: what each

The catalog data (apparatus, element groups, elements, vaults and variant groups) is extracted from the FIG Women's Artistic Gymnastics Code of Points 2025–2028 and is read-only in the app. The user data (coaches, gymnasts and routines) is created by users through the website.

Example data that shows how each entity is structured is in [examples/](examples/). The entries are invented and are for documentation only.

## Diagram

```mermaid
Expand Down
20 changes: 20 additions & 0 deletions docs/examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Example data

These JSON files show how the data described in [DATA_MODEL.md](../DATA_MODEL.md) is structured. They are documentation only and are not used by the app.

**The data is invented.** The apparatus and element group names are taken from the table of contents of the FIG Women's Artistic Gymnastics Code of Points 2025–2028. Everything else is made up: the elements, vaults, descriptions, names, coach and gymnasts. The codes and values follow the pattern of the Code of Points (`3.304` is an element in group 3 with value 0.3), but they do not match real elements. The image files named in the data do not exist.

**The data is generated by AI.** All the JSON files were generated by Claude Code from a task description written by the team. See [AI_USAGE.md](../AI_USAGE.md).

The ids of coaches, gymnasts and routines (`coach-1`, `gymnast-1`, `routine-1`) are placeholders for the internal ids the database will generate.

| File | Entity | Contents |
| -------------------- | ------------ | --------------------------------------------------------------------- |
| `apparatus.json` | Apparatus | All 4 apparatus |
| `elementGroups.json` | ElementGroup | All 22 element groups |
| `elements.json` | Element | 9 elements on uneven bars, beam and floor, including two variants |
| `vaults.json` | Vault | 2 vaults from different groups |
| `variantGroups.json` | VariantGroup | 1 variant group, linking the two variants of `UB-1.101` |
| `coaches.json` | Coach | 1 coach |
| `gymnasts.json` | Gymnast | 2 gymnasts with their lists of elements |
| `routines.json` | Routine | 5 routines, including two on the same apparatus and one vault routine |
6 changes: 6 additions & 0 deletions docs/examples/apparatus.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{ "id": "VT", "name": "Vault" },
{ "id": "UB", "name": "Uneven bars" },
{ "id": "BB", "name": "Balance beam" },
{ "id": "FX", "name": "Floor exercise" }
]
9 changes: 9 additions & 0 deletions docs/examples/coaches.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"id": "coach-1",
"googleId": "109876543210987654321",
"email": "kari.nilsen@example.com",
"name": "Kari Nilsen",
"createdAt": "2026-10-01T12:00:00Z"
}
]
84 changes: 84 additions & 0 deletions docs/examples/elementGroups.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
[
{
"id": "VT-1",
"apparatusId": "VT",
"number": 1,
"name": "Vaults without salto (handspring, Yamashita, round-off) with or without LA turn in 1st and/or 2nd flight phase"
},
{
"id": "VT-2",
"apparatusId": "VT",
"number": 2,
"name": "Handspring fwd with or without 1/1 turn (360°) in 1st flight phase – salto fwd or bwd with or without LA turn in 2nd flight phase"
},
{
"id": "VT-3",
"apparatusId": "VT",
"number": 3,
"name": "Handspring with ¼–½ turn (90°–180°) in 1st flight phase (Tsukahara) – salto bwd with or without LA turn in 2nd flight phase"
},
{
"id": "VT-4",
"apparatusId": "VT",
"number": 4,
"name": "Round-off (Yurchenko) with or without ¾ turn (270°) in 1st flight phase – salto bwd with or without LA turn in 2nd flight phase"
},
{
"id": "VT-5",
"apparatusId": "VT",
"number": 5,
"name": "Round-off with ½ turn (180°) in 1st flight phase – salto fwd or bwd with or without LA turn in 2nd flight phase"
},
{ "id": "UB-1", "apparatusId": "UB", "number": 1, "name": "Mounts" },
{
"id": "UB-2",
"apparatusId": "UB",
"number": 2,
"name": "Casts and clear hip circles"
},
{ "id": "UB-3", "apparatusId": "UB", "number": 3, "name": "Giant circles" },
{ "id": "UB-4", "apparatusId": "UB", "number": 4, "name": "Stalder circles" },
{ "id": "UB-5", "apparatusId": "UB", "number": 5, "name": "Pike circles" },
{ "id": "UB-6", "apparatusId": "UB", "number": 6, "name": "Dismounts" },
{ "id": "BB-1", "apparatusId": "BB", "number": 1, "name": "Mounts" },
{
"id": "BB-2",
"apparatusId": "BB",
"number": 2,
"name": "Gymnastic leaps, jumps and hops"
},
{ "id": "BB-3", "apparatusId": "BB", "number": 3, "name": "Gymnastic turns" },
{
"id": "BB-4",
"apparatusId": "BB",
"number": 4,
"name": "Holds and acrobatic non-flight"
},
{
"id": "BB-5",
"apparatusId": "BB",
"number": 5,
"name": "Acrobatic flight"
},
{ "id": "BB-6", "apparatusId": "BB", "number": 6, "name": "Dismounts" },
{
"id": "FX-1",
"apparatusId": "FX",
"number": 1,
"name": "Gymnastic leaps, jumps and hops"
},
{ "id": "FX-2", "apparatusId": "FX", "number": 2, "name": "Gymnastic turns" },
{
"id": "FX-3",
"apparatusId": "FX",
"number": 3,
"name": "Hand support elements"
},
{
"id": "FX-4",
"apparatusId": "FX",
"number": 4,
"name": "Saltos forward and sideward"
},
{ "id": "FX-5", "apparatusId": "FX", "number": 5, "name": "Saltos backward" }
]
83 changes: 83 additions & 0 deletions docs/examples/elements.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
[
{
"id": "UB-1.101-a",
"elementGroupId": "UB-1",
"code": "1.101",
"value": 0.1,
"description": "Jump with straight body to hang on HB – swing fwd with ½ turn (180°)",
"name": null,
"image": "UB-1.101-a.webp"
},
{
"id": "UB-1.101-b",
"elementGroupId": "UB-1",
"code": "1.101",
"value": 0.1,
"description": "Jump with legs straddled to hang on HB – swing fwd with ½ turn (180°)",
"name": null,
"image": "UB-1.101-b.webp"
},
{
"id": "UB-3.304-a",
"elementGroupId": "UB-3",
"code": "3.304",
"value": 0.3,
"description": "Giant circle bwd in mixed grip with ½ turn (180°) through handstand",
"name": null,
"image": "UB-3.304-a.webp"
},
{
"id": "BB-2.201-a",
"elementGroupId": "BB-2",
"code": "2.201",
"value": 0.2,
"description": "Leap fwd with ½ turn (180°), landing on one leg in cross position",
"name": null,
"image": "BB-2.201-a.webp"
},
{
"id": "BB-5.403-a",
"elementGroupId": "BB-5",
"code": "5.403",
"value": 0.4,
"description": "Salto swd tucked from a two-step approach, landing in side position",
"name": "Lindqvist",
"image": "BB-5.403-a.webp"
},
{
"id": "BB-6.305-a",
"elementGroupId": "BB-6",
"code": "6.305",
"value": 0.3,
"description": "Round-off at end of beam – salto bwd piked with ½ turn (180°)",
"name": null,
"image": "BB-6.305-a.webp"
},
{
"id": "FX-1.203-a",
"elementGroupId": "FX-1",
"code": "1.203",
"value": 0.2,
"description": "Hop with free leg at horizontal and 1/1 turn (360°)",
"name": null,
"image": "FX-1.203-a.webp"
},
{
"id": "FX-2.302-a",
"elementGroupId": "FX-2",
"code": "2.302",
"value": 0.3,
"description": "2/1 turn (720°) on one leg with free leg held bent in front",
"name": null,
"image": "FX-2.302-a.webp"
},
{
"id": "FX-5.506-a",
"elementGroupId": "FX-5",
"code": "5.506",
"value": 0.5,
"description": "Double salto bwd with first salto tucked and second salto piked, with 1/1 turn (360°)",
"name": "Aasen",
"image": "FX-5.506-a.webp"
}
]
21 changes: 21 additions & 0 deletions docs/examples/gymnasts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[
{
"id": "gymnast-1",
"coachId": "coach-1",
"name": "Ingrid Haugen",
"elementIds": [
"UB-1.101-a",
"UB-1.101-b",
"UB-3.304-a",
"BB-2.201-a",
"VT-1.12-a",
"VT-4.23-a"
]
},
{
"id": "gymnast-2",
"coachId": "coach-1",
"name": "Emma Berg",
"elementIds": ["BB-2.201-a", "BB-5.403-a", "FX-1.203-a", "FX-2.302-a"]
}
]
37 changes: 37 additions & 0 deletions docs/examples/routines.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"id": "routine-1",
"gymnastId": "gymnast-1",
"name": "Competition routine",
"apparatusId": "UB",
"elementIds": ["UB-1.101-a", "UB-3.304-a"]
},
{
"id": "routine-2",
"gymnastId": "gymnast-1",
"name": "With straddled mount",
"apparatusId": "UB",
"elementIds": ["UB-1.101-b", "UB-3.304-a"]
},
{
"id": "routine-3",
"gymnastId": "gymnast-1",
"name": "Competition vault",
"apparatusId": "VT",
"elementIds": ["VT-1.12-a"]
},
{
"id": "routine-4",
"gymnastId": "gymnast-2",
"name": "Competition routine",
"apparatusId": "BB",
"elementIds": ["BB-2.201-a", "BB-5.403-a", "BB-6.305-a"]
},
{
"id": "routine-5",
"gymnastId": "gymnast-2",
"name": "Competition routine",
"apparatusId": "FX",
"elementIds": ["FX-1.203-a", "FX-2.302-a", "FX-5.506-a"]
}
]
Loading