- Python 58%
- HTML 20.5%
- CSS 16%
- JavaScript 4.5%
- Jinja 0.9%
- Other 0.1%
| .github | ||
| deploy | ||
| doc | ||
| genepy_org | ||
| hkis | ||
| locale/fr/LC_MESSAGES | ||
| templates | ||
| .gitignore | ||
| correction_bot.py | ||
| docker-compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| manage.py | ||
| mypy.ini | ||
| pyproject.toml | ||
| README-docker.md | ||
| README.md | ||
| requirements-dev.txt | ||
| requirements.txt | ||
Genepy
Genepy is an open-source platform to practice any programming language with live feedback. The canonical instance of Genepy, to practice Python, is known as Genepy.org had already been teaching Python to 25k+ users.
Documentation
The pages
A page is literally a URL in your site, it can contain text (stored Markdown) and/or exercises.
For example the automatically created page at /help is aimed to
store text but no exercises, and the page at /exercises is aimed to
present some exercises, maybe after an intro text, or without any
text.
You can live with only those two pages, or create a whole set of pages like one exercise page per programming language, or per topic, per student class, ...
Once logged, the users are redirected to the first page (the one with
the smallest position).
The tags
Exercises can optionally be tagged, like easy, numpy, rust, or
whatever helps you organize your exercises. Exercises can have
multiple tags.
Stats
I like getting some stats from the DB like:
Time to give a correction
SELECT date_trunc('month', created_at) m,
TO_CHAR(min(corrected_at - created_at), 'MI:SS.MS') min,
TO_CHAR(max(corrected_at - created_at), 'MI:SS.MS') max,
TO_CHAR(avg(corrected_at - created_at), 'MI:SS.MS') avg1,
PERCENTILE_CONT(0.5) WITHIN GROUP(ORDER BY (corrected_at - created_at)) median
FROM hkis_answer
WHERE is_corrected AND created_at > now() - interval '1 year'
GROUP BY m
ORDER BY m;
On genepy.org the median went from 0.7s (march 2022) to 0.4s (march 2023), back to 0.5s (October 2024). Beware there's always students running infinite loops so the max can't be low.
Success ratio on exercises
SELECT exercise.title_en,
COUNT(1), 100 * SUM(CASE WHEN answer.is_valid THEN 1 ELSE 0 END)/COUNT(1) "success ratio"
FROM hkis_answer answer
JOIN hkis_exercise exercise ON exercise.id = answer.exercise_id
WHERE answer.created_at > NOW() - INTERVAL '1 week'
GROUP BY exercise.id, exercise.title_en, exercise.position
ORDER BY exercise.position;
Inscriptions
SELECT COUNT(1), TO_CHAR(DATE_TRUNC('day', date_joined), 'YYYY-MM-DD Day') d
FROM auth_user
WHERE date_joined > DATE_TRUNC('day', NOW() - INTERVAL '31 day')
GROUP BY d
ORDER BY d;
How does the checker bot work?
The answers are load-balanced to correction workers using Redis, so you can have multiple machines dedicated to correct loads of answers.
Once received by a worker the worker runs two things:
- A
check.pyscript is then started in a sandbox (no internet connectivity, restricted file system, CPU, memory usage, …). This is the script that check the student answer, the protocol is simple: if the script exits with non-zero, then answer is wrong. And what's been printed (bothstdoutandstderr) is displayed, as Markdown, to the student. If the answer is right and nothing is printed, a default congratulation message is used.
check.py is to be written in Python, but it's not limited to check
Python answers, if you want to check for shell script or C, or
whatever, the check.py can use subprocess to run the answer
script, or compile the answer code, or whatever needed.