Skip to content

Commit ac43286

Browse files
author
Nils Bars
committed
Rename scoreboard 'wave' to 'assignment' and document optional features
- Replace 'wave' with 'assignment' in SCOREBOARD.md and in comments and user-facing strings under webapp/ref/{view/api.py, core/scoring.py, model/exercise_config.py}. - Add an "Optional Features" section to README.md describing the groups and scoreboard settings, both disabled by default and configured from the admin system-settings page.
1 parent f6a334d commit ac43286

5 files changed

Lines changed: 26 additions & 17 deletions

File tree

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,12 @@ User: ref
176176
Database name: ref
177177
Password: See settings.yaml (secrets.postgres_password)
178178
```
179+
180+
### Optional Features
181+
The following features are disabled by default and can be enabled from the admin UI at `/admin/system/settings/`.
182+
183+
#### Groups
184+
Allows students to be organized into named groups with a configurable maximum size. Students pick a group during registration, and admins can manage the available groups and reassign students afterwards. Enable via the `GROUPS_ENABLED` setting and configure the per-group capacity via `GROUP_SIZE`.
185+
186+
#### Scoreboard
187+
A public leaderboard at `/scoreboard` that ranks students based on their exercise submissions. Exercises can be grouped into assignments, the ranking strategy is selected via `SCOREBOARD_RANKING_MODE`, and the visual layout via `SCOREBOARD_VIEW`. Enable via `SCOREBOARD_ENABLED`; optionally set `LANDING_PAGE` to `scoreboard` to use it as the default landing page.

docs/SCOREBOARD.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,25 @@ This document describes how to integrate a scoreboard into REF, based on the pro
44

55
## Overview
66

7-
The scoreboard is a public-facing page that shows team/student rankings based on submission scores. Exercises are grouped into **waves** (time-boxed rounds). Each exercise defines a **scoring policy** that maps raw submission scores to scoreboard points. The frontend fetches data via two JSON APIs and renders rankings, badges, charts, and per-challenge plots client-side.
7+
The scoreboard is a public-facing page that shows team/student rankings based on submission scores. Exercises are grouped into **assignments** (time-boxed rounds). Each exercise defines a **scoring policy** that maps raw submission scores to scoreboard points. The frontend fetches data via two JSON APIs and renders rankings, badges, charts, and per-challenge plots client-side.
88

99
## What exists in `raid/raid`
1010

1111
The prototype adds:
1212

13-
- **Two API endpoints** (`/api/waves`, `/api/submissions`) that return exercise metadata and submission scores as JSON.
13+
- **Two API endpoints** (`/api/assignments`, `/api/submissions`) that return exercise metadata and submission scores as JSON.
1414
- **Three new Exercise model fields**: `baseline_score`, `badge_score`, `badge_points` — parsed from the exercise YAML config.
1515
- **A scoreboard page** (`/student/scoreboard`) with a Jinja template and ~2300 lines of client-side JS (`scoreboard.js`, `utils.js`, `plots.js`) using Chart.js.
1616
- **Badges**: per-challenge achievement icons shown in the ranking table when a team's score exceeds `badge_score`. Each challenge can have custom SVG/PNG assets with a default fallback.
1717
- **System settings**: `LANDING_PAGE` (choose which page students see first), `DEMO_MODE_ENABLED` (serve dummy JSON data).
18-
- **A demo/dummy data system** (`dummies/waves.json`, `dummies/submissions.json`) for development without real submissions.
18+
- **A demo/dummy data system** (`dummies/assignments.json`, `dummies/submissions.json`) for development without real submissions.
1919

20-
The prototype is tightly coupled to a fixed 3-waves x 3-challenges layout and hardcodes wave/challenge indices in the template. It also bundles all scoring logic (ranking, badges, rates) in the frontend JS.
20+
The prototype is tightly coupled to a fixed 3-assignments x 3-challenges layout and hardcodes assignment/challenge indices in the template. It also bundles all scoring logic (ranking, badges, rates) in the frontend JS.
2121

2222
## What already exists in `dev`
2323

2424
- `SubmissionTestResult.score` (float, nullable) — already in the model. This is the raw per-submission score.
25-
- Exercise `category` field — used as the wave/group name.
25+
- Exercise `category` field — used as the assignment/group name.
2626
- `Submission.all()`, exercise deadlines, the full submission lifecycle.
2727

2828
## ExerciseConfig: Separating Administrative from Build-Time Config
@@ -41,7 +41,7 @@ class ExerciseConfig(db.Model):
4141

4242
id: Mapped[int] # PK (integer)
4343
short_name: Mapped[str] # unique constraint
44-
category: Mapped[Optional[str]] # wave/group name
44+
category: Mapped[Optional[str]] # assignment/group name
4545
scoring_policy: Mapped[Optional[dict]] # JSON, see Scoring Architecture
4646
submission_deadline_start: Mapped[Optional[datetime]]
4747
submission_deadline_end: Mapped[Optional[datetime]]
@@ -96,7 +96,7 @@ Future candidates for `ExerciseConfig`: display name, description, visibility/pu
9696

9797
The exercise list page gets an **Edit** button per exercise (per `short_name`, not per version). It opens a form editing the `ExerciseConfig`:
9898

99-
- Category / wave assignment
99+
- Category / assignment
100100
- Deadlines (start, end)
101101
- Scoring policy (mode selector + mode-specific fields)
102102
- Max grading points
@@ -166,11 +166,11 @@ The migration:
166166

167167
### 3. Scoring API Endpoints
168168

169-
**`GET /api/scoreboard/config`** — Returns exercise metadata grouped by `category` (wave), including the scoring policy:
169+
**`GET /api/scoreboard/config`** — Returns exercise metadata grouped by `category` (assignment), including the scoring policy:
170170

171171
```json
172172
{
173-
"Wave 1": {
173+
"Assignment 1": {
174174
"exercise_name": {
175175
"start": "...",
176176
"end": "...",
@@ -203,7 +203,7 @@ Both endpoints are rate-limited and publicly accessible (no auth required).
203203

204204
Add an edit button to the exercise list page. The edit form modifies `ExerciseConfig` fields:
205205

206-
- Category / wave
206+
- Category / assignment
207207
- Deadlines
208208
- Scoring policy (mode dropdown + dynamic fields per mode)
209209
- Max grading points
@@ -216,9 +216,9 @@ Add a scoreboard page at `/scoreboard`:
216216
- Fetches `/api/scoreboard/config` and `/api/submissions` periodically.
217217
- Renders a **ranking table** (sorted by total points) with **badge icons** for earned challenges.
218218
- Renders **per-challenge score charts** using Chart.js with baseline annotation lines.
219-
- Shows a **countdown timer** for the active wave's deadline.
220-
- Supports multiple waves via tab navigation.
221-
- Fully dynamic — number of waves and challenges driven by API data.
219+
- Shows a **countdown timer** for the active assignment's deadline.
220+
- Supports multiple assignments via tab navigation.
221+
- Fully dynamic — number of assignments and challenges driven by API data.
222222

223223
The `raid/raid` JS can be reused but should be refactored to remove the hardcoded 3x3 layout.
224224

webapp/ref/core/scoring.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
# independent of the ranking strategy — views share utils.js and the
4040
# ranking/*.js modules. Adding a new view is one dict entry + two files.
4141
SCOREBOARD_VIEWS: dict[str, str] = {
42-
"default": "Default (waves, charts, badges)",
42+
"default": "Default (assignments, charts, badges)",
4343
"minimal": "Minimal (ranking table only)",
4444
}
4545
DEFAULT_SCOREBOARD_VIEW = "default"

webapp/ref/model/exercise_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ExerciseConfig(CommonDbOpsMixin, ModelToStringMixin, db.Model):
2525
id: Mapped[int] = mapped_column(primary_key=True)
2626
short_name: Mapped[str] = mapped_column(Text, unique=True)
2727

28-
# Used to group exercises (e.g., wave name for scoreboard)
28+
# Used to group exercises (e.g., assignment name for scoreboard)
2929
category: Mapped[Optional[str]] = mapped_column(Text)
3030

3131
submission_deadline_start: Mapped[Optional[datetime.datetime]]

webapp/ref/view/api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,8 +1001,8 @@ def api_scoreboard_config():
10011001
}
10021002

10031003
# The outer grouping key is `ExerciseConfig.category` — whatever label
1004-
# the admin chose in the exercise config edit form (e.g. "Assignment 1",
1005-
# "Wave 1", "Phase A"). Rendered verbatim by the frontend.
1004+
# the admin chose in the exercise config edit form (e.g. "Assignment 1"
1005+
# or "Phase A"). Rendered verbatim by the frontend.
10061006
assignments: dict[str, dict[str, dict]] = defaultdict(dict)
10071007
configs = ExerciseConfig.query.filter(
10081008
ExerciseConfig.category.isnot(None),

0 commit comments

Comments
 (0)