From fef44af47f3d29455ba0f5de0a8cd9daac36583b Mon Sep 17 00:00:00 2001 From: BrechtW <56451049+BTWS2@users.noreply.github.com> Date: Thu, 7 Jul 2022 13:51:03 +0200 Subject: [PATCH 1/4] readme --- README.md | 147 +++++++++++++++++++++++++++++++++++++++++++- judge/translator.py | 8 +-- 2 files changed, 148 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e8eb748..90e8452 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,145 @@ -# judge-turtle -🐢 Python Turtle judge for the Dodona learning environment +# Python Turtle for [Dodona](https://dodona.ugent.be/) -***Python Turtle** graphics is a popular way for introducing programming to kids. This judge aims to provide **feedback** for these students during the learning experience and evaluations. How similar is the submission of the student to the solution of the teacher?* +> ***Python Turtle** graphics is a popular way for introducing programming to kids. This judge aims to provide **feedback** for these students during the learning experience and evaluations. How similar is the submission of the student to the solution of the teacher?* +> +> ![Python Turtle judge demo](judge-turtle.png) +> +> This Dodona course contains some sample exercises that were used in developing the Python Turtle judge: +> +> * https://dodona.ugent.be/en/courses/TODO/ +> +> There are a number of sample exercises on Dodona's sample exercises repository to demonstrate the use of the judge: +> +> * https://github.com/dodona-edu/example-exercises # TODO +> + +### Judge features + +* Comparison based on solution Python file +* Submission and solution image shown side-by-side +* Absolute difference and percentage of mismatched visible (non-transparant) pixels. +* Option to set custom canvas size in `config.json` +* Feedback in language of user (Dutch or English) + +### Judge properties + +* `print()` statements and `time.sleep()` are ignored. +* No intermediary steps ar shown. Only the end result is compared. +* Judge accepts solution independent of code. The judge doesn't make a destination between e.g. square drawn with for-loop or not. If a figure is drawn clockwise or counterclockwise it's treated equally. +* Support for transparency. +* Script available to convert `solution.py` to svg image for exercise description. + +## Recommended exercise directory structure + +> [More info about repository directory structure](https://docs.dodona.be/en/references/repository-directory-structure/#example-of-a-valid-repository-structure) + +Add your solution file (`solution.py`) the **`evaluation`** folder. You can define a different name for the solution in the `config.json` file. Absolute +necessary files are marked with `▶` in the tree structure below. + +```text ++-- README.md # Optional: Describes the repository ++-- dirconfig.json # Shared config for all exercises in subdirs ++-- 📂public # Optional: Contains files that belong to the course or series +| +-- my_turtle.png # Optional: An image to reuse throughout the course ++-- 📂turtle-exercises # We could group exercises in a folder +| +-- 📂rectangle # Folder name for the exercise +| | +-- config.json # ▶ Configuration of the exercise (explained later) +| | +-- 📂evaluation # -- 🔽️ ADD YOUR SOLUTION HERE 🔽 -- +| | | +-- solution.py # ▶ The Python Turtle model solution file +| | +-- 📂solution # Optional: This will be visible in Dodona for teachers +| | | +-- solution.sql # Optional: The Python Turtle model solution file +| | +-- 📂description # +| | +-- description.nl.md # ▶ The description in Dutch +| | +-- description.en.md # Optional: The description in English +| | +-- 📂media # Optional folder +| | | +-- rectangle.svg # Optional: An image used in the description +| | +-- 📂boilerplate # Optional folder +| | +-- boilerplate # Optional: loaded automatically in submission text area +| : +: +``` + +## Recommended `dirconfig.json` + +> [More info about exercise directory structure](https://docs.dodona.be/en/references/exercise-directory-structure/) + +```json +{ + "type": "exercise", + "programming_language": "python", + "access": "public", + "evaluation": { + "handler": "turtle", + "time_limit": 10 + }, + "labels": [ + "turtle" + ], + "author": "Firstname Lastname ", + "contact": "firstname_lastname@ugent.be" +} +``` + +## Recommended `config.json` (example with default settings) + +```json +{ + "description": { + "names": { + "nl": "Mijn eerste Python Turtle oefening", + "en": "My first Python Turtle exercise" + } + }, + "type": "exercise", + "programming_language": "turtle", + "access": "public", + "labels": [ + "turtle" + ], + "evaluation": { + "handler": "turtle", + "canvas_width": 400, + "canvas_height": 250 + } +} +``` + +## Optional `evaluation` settings in `config.json` + +If these settings are not defined, the default value is chosen. + +| Evaluation setting | Description | Possible values | Default | +|--------------------|--------------------------------|-----------------|-----------------| +| `solution_file` | Relative path to solution file | path | `./solution.py` | +| `canvas_width` | Width of canvas in pixels | int | `400` | +| `canvas_height` | Height of canvas in pixels | int | `250` | + +## Generator script + +The svg images for each exercise can be made with a Python script. Place the script at the root of your folder with exercises. + +````python +# TODO +```` + +#### Show svg image in Dodona description + +- Markdown (recommended) + +```markdown +![image_name](./media/image_name.svg){:height="50%" width="50%"}{: style="border-style: inset"} +``` + +- HTML + +```html +image_name +``` + +## Contributors + +- **T. Ramlot** +- B. Willems + +_Development funded by the [Faculty of Engineering and Architecture](https://www.ugent.be/ea/en) +of [Ghent University](https://www.ugent.be/en)_ \ No newline at end of file diff --git a/judge/translator.py b/judge/translator.py index 4590507..00673ef 100755 --- a/judge/translator.py +++ b/judge/translator.py @@ -125,8 +125,8 @@ def translate(self, message: Text, **kwargs: Any) -> str: Text.COMPARING_IMAGES: "Comparing images", Text.SOLUTION_EXECUTION_ERROR: "Error executing solution script:\n {error}", Text.SUBMISSION_EXECUTION_ERROR: "Error executing submission script:\n {error}", - Text.SOLUTION_TITLE: "Submission:", - Text.SUBMISSION_TITLE: "Solution:", + Text.SOLUTION_TITLE: "Solution:", + Text.SUBMISSION_TITLE: "Submission:", Text.FOREGROUND_PIXELS_CORRECT: "{correct_pixels}/{total_pixels} " "({fraction:.1%}) visible pixels correct", }, @@ -134,8 +134,8 @@ def translate(self, message: Text, **kwargs: Any) -> str: Text.COMPARING_IMAGES: "Afbeeldingen vergelijken", Text.SOLUTION_EXECUTION_ERROR: "Error bij het uitvoeren van het oplossingsscript:\n {error}", Text.SUBMISSION_EXECUTION_ERROR: "Error bij het uitvoeren van het ingediende script:\n {error}", - Text.SOLUTION_TITLE: "Indiening:", - Text.SUBMISSION_TITLE: "Oplossing:", + Text.SOLUTION_TITLE: "Oplossing:", + Text.SUBMISSION_TITLE: "Indiening:", Text.FOREGROUND_PIXELS_CORRECT: "{correct_pixels}/{total_pixels} " "({fraction:.1%}) zichtbare pixels correct", }, From 08188cd30b7f4bc2c959680f91c3568bc720bd34 Mon Sep 17 00:00:00 2001 From: BrechtW <56451049+BTWS2@users.noreply.github.com> Date: Thu, 7 Jul 2022 13:59:34 +0200 Subject: [PATCH 2/4] switch submission solution --- tests/e2e_stdout/test-turtle-judge/oef1_noImport.stdout | 2 +- tests/e2e_stdout/test-turtle-judge/oef1_non_transparent.stdout | 2 +- tests/e2e_stdout/test-turtle-judge/oef1_print.stdout | 2 +- tests/e2e_stdout/test-turtle-judge/oef1_sleep.stdout | 2 +- tests/e2e_stdout/test-turtle-judge/oef1_solution.stdout | 2 +- tests/e2e_stdout/test-turtle-judge/oef2_solution.stdout | 2 +- tests/e2e_stdout/test-turtle-judge/oef3_solution.stdout | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/e2e_stdout/test-turtle-judge/oef1_noImport.stdout b/tests/e2e_stdout/test-turtle-judge/oef1_noImport.stdout index 01a9115..21c11bd 100644 --- a/tests/e2e_stdout/test-turtle-judge/oef1_noImport.stdout +++ b/tests/e2e_stdout/test-turtle-judge/oef1_noImport.stdout @@ -18,7 +18,7 @@ { "command": "start-test", "description": { - "description": "

Oplossing:

\"submission

Indiening:

\"solution
", + "description": "

Indiening:

\"submission

Oplossing:

\"solution
", "format": "html" }, "expected": "400/400 (100.0%) zichtbare pixels correct" diff --git a/tests/e2e_stdout/test-turtle-judge/oef1_non_transparent.stdout b/tests/e2e_stdout/test-turtle-judge/oef1_non_transparent.stdout index 5aed8da..4edea24 100644 --- a/tests/e2e_stdout/test-turtle-judge/oef1_non_transparent.stdout +++ b/tests/e2e_stdout/test-turtle-judge/oef1_non_transparent.stdout @@ -18,7 +18,7 @@ { "command": "start-test", "description": { - "description": "

Oplossing:

\"submission

Indiening:

\"solution
", + "description": "

Indiening:

\"submission

Oplossing:

\"solution
", "format": "html" }, "expected": "400/400 (100.0%) zichtbare pixels correct" diff --git a/tests/e2e_stdout/test-turtle-judge/oef1_print.stdout b/tests/e2e_stdout/test-turtle-judge/oef1_print.stdout index 7b9029b..9aa496a 100644 --- a/tests/e2e_stdout/test-turtle-judge/oef1_print.stdout +++ b/tests/e2e_stdout/test-turtle-judge/oef1_print.stdout @@ -18,7 +18,7 @@ { "command": "start-test", "description": { - "description": "

Oplossing:

\"submission

Indiening:

\"solution
", + "description": "

Indiening:

\"submission

Oplossing:

\"solution
", "format": "html" }, "expected": "400/400 (100.0%) zichtbare pixels correct" diff --git a/tests/e2e_stdout/test-turtle-judge/oef1_sleep.stdout b/tests/e2e_stdout/test-turtle-judge/oef1_sleep.stdout index 01a9115..21c11bd 100644 --- a/tests/e2e_stdout/test-turtle-judge/oef1_sleep.stdout +++ b/tests/e2e_stdout/test-turtle-judge/oef1_sleep.stdout @@ -18,7 +18,7 @@ { "command": "start-test", "description": { - "description": "

Oplossing:

\"submission

Indiening:

\"solution
", + "description": "

Indiening:

\"submission

Oplossing:

\"solution
", "format": "html" }, "expected": "400/400 (100.0%) zichtbare pixels correct" diff --git a/tests/e2e_stdout/test-turtle-judge/oef1_solution.stdout b/tests/e2e_stdout/test-turtle-judge/oef1_solution.stdout index 7b9029b..9aa496a 100644 --- a/tests/e2e_stdout/test-turtle-judge/oef1_solution.stdout +++ b/tests/e2e_stdout/test-turtle-judge/oef1_solution.stdout @@ -18,7 +18,7 @@ { "command": "start-test", "description": { - "description": "

Oplossing:

\"submission

Indiening:

\"solution
", + "description": "

Indiening:

\"submission

Oplossing:

\"solution
", "format": "html" }, "expected": "400/400 (100.0%) zichtbare pixels correct" diff --git a/tests/e2e_stdout/test-turtle-judge/oef2_solution.stdout b/tests/e2e_stdout/test-turtle-judge/oef2_solution.stdout index 30498e1..00f40da 100644 --- a/tests/e2e_stdout/test-turtle-judge/oef2_solution.stdout +++ b/tests/e2e_stdout/test-turtle-judge/oef2_solution.stdout @@ -18,7 +18,7 @@ { "command": "start-test", "description": { - "description": "

Oplossing:

\"submission

Indiening:

\"solution
", + "description": "

Indiening:

\"submission

Oplossing:

\"solution
", "format": "html" }, "expected": "20/20 (100.0%) zichtbare pixels correct" diff --git a/tests/e2e_stdout/test-turtle-judge/oef3_solution.stdout b/tests/e2e_stdout/test-turtle-judge/oef3_solution.stdout index fcb8c70..8e1d3eb 100644 --- a/tests/e2e_stdout/test-turtle-judge/oef3_solution.stdout +++ b/tests/e2e_stdout/test-turtle-judge/oef3_solution.stdout @@ -18,7 +18,7 @@ { "command": "start-test", "description": { - "description": "

Oplossing:

\"submission

Indiening:

\"solution
", + "description": "

Indiening:

\"submission

Oplossing:

\"solution
", "format": "html" }, "expected": "10000/10000 (100.0%) zichtbare pixels correct" From 4e7c66619811f43ae171da088c3c2561677a1faa Mon Sep 17 00:00:00 2001 From: BrechtW <56451049+BTWS2@users.noreply.github.com> Date: Thu, 7 Jul 2022 14:06:03 +0200 Subject: [PATCH 3/4] readme --- README.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 90e8452..9c09400 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,22 @@ > > This Dodona course contains some sample exercises that were used in developing the Python Turtle judge: > -> * https://dodona.ugent.be/en/courses/TODO/ +> * > > There are a number of sample exercises on Dodona's sample exercises repository to demonstrate the use of the judge: > -> * https://github.com/dodona-edu/example-exercises # TODO +> * # TODO > +## Table of Contents + +* [Recommended exercise directory structure](#recommended-exercise-directory-structure) +* [Recommended `dirconfig.json`](#recommended-dirconfigjson) +* [Recommended `config.json` (example with default settings)](#recommended-configjson-example-with-default-settings) +* [Optional `evaluation` settings in `config.json`](#optional-evaluation-settings-in-configjson) +* [Generator script](#generator-script) +* [Contributors](#contributors) + ### Judge features * Comparison based on solution Python file @@ -124,13 +133,13 @@ The svg images for each exercise can be made with a Python script. Place the scr #### Show svg image in Dodona description -- Markdown (recommended) +* Markdown (recommended) ```markdown ![image_name](./media/image_name.svg){:height="50%" width="50%"}{: style="border-style: inset"} ``` -- HTML +* HTML ```html image_name @@ -138,8 +147,8 @@ The svg images for each exercise can be made with a Python script. Place the scr ## Contributors -- **T. Ramlot** -- B. Willems +* **T. Ramlot** +* B. Willems -_Development funded by the [Faculty of Engineering and Architecture](https://www.ugent.be/ea/en) -of [Ghent University](https://www.ugent.be/en)_ \ No newline at end of file +*Development funded by the [Faculty of Engineering and Architecture](https://www.ugent.be/ea/en) +of [Ghent University](https://www.ugent.be/en)* From c0cafe6f4d945777d141c724f8a6e2857d895c78 Mon Sep 17 00:00:00 2001 From: BrechtW <56451049+BTWS2@users.noreply.github.com> Date: Thu, 7 Jul 2022 14:10:24 +0200 Subject: [PATCH 4/4] readme --- README.md | 27 ++++++++++++++------------- judge-turtle.png | Bin 0 -> 27812 bytes 2 files changed, 14 insertions(+), 13 deletions(-) create mode 100644 judge-turtle.png diff --git a/README.md b/README.md index 9c09400..3179709 100644 --- a/README.md +++ b/README.md @@ -13,20 +13,11 @@ > * # TODO > -## Table of Contents - -* [Recommended exercise directory structure](#recommended-exercise-directory-structure) -* [Recommended `dirconfig.json`](#recommended-dirconfigjson) -* [Recommended `config.json` (example with default settings)](#recommended-configjson-example-with-default-settings) -* [Optional `evaluation` settings in `config.json`](#optional-evaluation-settings-in-configjson) -* [Generator script](#generator-script) -* [Contributors](#contributors) - ### Judge features * Comparison based on solution Python file * Submission and solution image shown side-by-side -* Absolute difference and percentage of mismatched visible (non-transparant) pixels. +* Absolute difference and percentage of mismatched visible (non-transparant) pixels * Option to set custom canvas size in `config.json` * Feedback in language of user (Dutch or English) @@ -38,6 +29,15 @@ * Support for transparency. * Script available to convert `solution.py` to svg image for exercise description. +## Table of Contents + +* [Recommended exercise directory structure](#recommended-exercise-directory-structure) +* [Recommended `dirconfig.json`](#recommended-dirconfigjson) +* [Recommended `config.json` (example with default settings)](#recommended-configjson-example-with-default-settings) +* [Optional `evaluation` settings in `config.json`](#optional-evaluation-settings-in-configjson) +* [Generator script](#generator-script) +* [Contributors](#contributors) + ## Recommended exercise directory structure > [More info about repository directory structure](https://docs.dodona.be/en/references/repository-directory-structure/#example-of-a-valid-repository-structure) @@ -56,7 +56,7 @@ necessary files are marked with `▶` in the tree structure below. | | +-- 📂evaluation # -- 🔽️ ADD YOUR SOLUTION HERE 🔽 -- | | | +-- solution.py # ▶ The Python Turtle model solution file | | +-- 📂solution # Optional: This will be visible in Dodona for teachers -| | | +-- solution.sql # Optional: The Python Turtle model solution file +| | | +-- solution.py # Optional: The Python Turtle model solution file | | +-- 📂description # | | +-- description.nl.md # ▶ The description in Dutch | | +-- description.en.md # Optional: The description in English @@ -79,7 +79,8 @@ necessary files are marked with `▶` in the tree structure below. "access": "public", "evaluation": { "handler": "turtle", - "time_limit": 10 + "time_limit": 10, + "memory_limit": 50000000 }, "labels": [ "turtle" @@ -128,7 +129,7 @@ If these settings are not defined, the default value is chosen. The svg images for each exercise can be made with a Python script. Place the script at the root of your folder with exercises. ````python -# TODO +# TODO, see https://github.com/BTWS2/judge-turtle/issues/16 ```` #### Show svg image in Dodona description diff --git a/judge-turtle.png b/judge-turtle.png new file mode 100644 index 0000000000000000000000000000000000000000..0c496174ff2f8d4b3e967b602ec0bbb1336c1eee GIT binary patch literal 27812 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