A dynamic quiz program that loads quizzes from quiz files!
- General Information
- Installation
- Command-Line Interface
- Create Quiz Files
- Builtin Quiz Types
- Plugin Development
-
Version: 1.1
-
GitHub: QuizEnchanter on GitHub
-
Python version: 3.11, 3.12 or 3.13
- Initially designed as a vocabulary trainer.
_Scaui (scaui0 on GitHub) is the developer of this project.
-
Open QuizEnchanter on GitHub in your favorite browser.
-
Click on the green button and select "Download ZIP".
-
Navigate to your download folder; then extract the downloaded ZIP file.
-
Download Python from the official website and follow the installation instructions for your operating system.
-
Open the command line on your computer. On Windows, you can do this by searching for and opening
cmd
. -
Use the
cd
command to navigate inside the extracted folder. -
Execute the following command to install all required packages:
pip install -r requirements.txt
. If it fails, trypython -m pip install -r requirements.txt
instead. -
To run the project, use
python QuizEnchanter.py
. You can specify additional arguments if needed. For more information, see Command-Line Interface. -
Then you will be asked which quiz file you want to run. You can use one of these default quizzes:
example.json
test.json
geography.json
example_plugin
(not.json
!): This is a quiz that uses a plugin. See above to see how to create a plugin.
You can also create your own quiz. See Create Quiz Files.
The command-line interface for QuizEnchanter is as follows:
usage: QuizEnchanter [-h] [file]
A quiz program
positional arguments:
file optional, absolute path to a quiz file or a relative path starts from quizzes folder
options:
-h, --help show this help message and exit
Run python QuizEnchanter.py
to run the program without arguments.
Because it doesn't know which quiz it has to start, it will ask you.
That is the simplest option to launch a quiz file.
Quiz file (in quizzes folder): test.json
Welcome to 'Test Quizzes'!
Please answer the following questions!
Please answer 'HI'!
Answer: HI
...
If you don't want to insert the quiz's name after starting the program, you can use the file argument of the program. When the file is set, the program will launch it. The file must be an absolute path to a quiz file.
python QuizEnchanter.py C:/Users/<USERNAME>/Desktop/quiz.json
:
Welcome to 'Test Quizzes'!
Please answer the following questions!
...
Do you want to create your own quizzes? Let's do this!
Here is a step-by-step guide:
-
Create a JSON file with a .json extension.
-
If you're not familiar with JSON, read this guide: JSON guide.
-
First, you need to assign a name to your quiz file. Then, the file will look like this:
{ "name": "Example Quiz" }
-
Then you need to add some questions. A question is an object in the
quizzes
array. You need to add atype
to each question. Then you can add some more information, that will be passed to the appropriate quiz type.There are six builtin quiz types you can use:
Quiz Type Short Description select
Select one from a list of options. match
User's answer is a string. bool
The user decides whether a statement is true. datetime
A time in ISO 8601. timeperiod
A time period in ISO 8601. message
Shows a message More information, like JSON fields for every builtin quiz type, can be found in Builtin Quiz Types.
Here is a short example:
{ "name": "Test Quizzes", "quizzes": [ { "type": "match", "question": "Please answer 'HI'!", "correct": "HI" }, { "type": "bool", "question": "This is true!", "correct": true }, { "type": "select", "question": "The first is correct!", "options": ["1", "2", "3", "4"], "correct": 0 }, { "type": "datetime", "question": "Please answer 2000-01-01!", "correct": "2000-01-01", "show_format_information": false }, { "type": "timeperiod", "question": "How looks a three-day period in ISO 8601?", "correct": "P3D", "show_format_information": false }, { "type": "message", "message": "This is a message!" } ] }
It isn't very useful, but it is still an example.
-
Move your quiz into the
quizzes
folder, run theQuizEnchanter.py
file with Python and write the name of your quiz file.
Quiz Type | Short Description |
---|---|
select |
Select one from a list of options. |
match |
User's answer is a string. |
bool |
The user decides whether a statement is true. |
datetime |
A time in ISO 8601. |
timeperiod |
A time period in ISO 8601. |
message |
Shows a message. |
This quiz type allows creating multiple-choice questions with predefined answer options.
Argument | Type | Information | Required |
---|---|---|---|
question | String | The question | true |
options | Array of Strings | The list of options the user could select | true |
correct | Int or array of ints | Correct index(es). All indexes start from 0! | false |
Example:
{
"type": "select",
"question": "Which mountain the the highest one?",
"options": ["Fuji", "Mount Everest", "Zugspitze"],
"correct": 1
}
The answer to the question is a string.
Argument | Type | Information | Required | Default |
---|---|---|---|---|
question | String | The question | true | |
strip_start_and_end | Bool | Strip whitespaces around the answer | false | true |
correct | Int or array of ints | The correct answer/answers | false | The answer cannot be correct. If you just want to check a regex, you can use the is_correct_when field |
ignore_case | Bool | Ignore case | false | false |
regex | String | Answer must match the regex (Python-dialect). The ignore_case option is not used for regexes |
false | .* (matches all answers) |
is_correct_when | String | Indicates when the answer should be correct. See description below | false | regex_and_in_correct |
The is_correct_when
field has three possible values:
Value | Answer is correct if |
---|---|
regex |
the regex matches |
in_rihgt |
if the inputted string in the correct answer is |
regex_and_in_correct |
the both things above matches |
Example without the regex
field:
{
"type": "match",
"question": "English or German greeting, beginning with 'h'?",
"correct": ["hello", "hallo"],
"ignore_case": true
}
The same example using the regex
field:
{
"type": "match",
"question": "English or German greeting, beginning with 'h'?",
"regex": "(?i)h[ae]llo"
}
The user has to decide whether the statement is correct.
Argument | Type | Information | Required |
---|---|---|---|
question | String | The question (actually a statement) | true |
correct | Bool | Indicates whether the question’s answer is correct | true |
Example:
{
"type": "bool",
"question": "Mount Everest is the highest mountain on Earth.",
"correct": true
}
This quiz type asks the user for a specific date or time in ISO 8601 format.
The simplified format is YYYY-MM-DDThh:mm:ss
.
If only the date or time is needed, the other part can be omitted.
The T
is used as a separator between the date and the time.
If you want to check a time period, you can use the timeperiod
quiz type
Argument | Type | Information | Required | Default |
---|---|---|---|---|
question | String | The question | true | |
correct | String or array of strings | The correct date(s) in ISO 8601 format | true | |
show_format_information | Bool | Shows a message about the date format to the user | false | true |
Example:
{
"type": "datetime",
"question": "On which date in 2000 was Christmas?",
"correct": ["2000-12-24", "2000-12-25", "2000-12-26"]
}
A timeperiod in ISO 8601.
Argument | Type | Information | Required |
---|---|---|---|
question | String | The question | true |
correct | String or array of strings | The correct time period(s) | true |
Example:
{
"type": "timeperiod",
"question": "How long is the period between St. Nicholas and Christmas?",
"correct": ["P18D", "P19D"]
}
Shows a message.
Argument | Type | Information | Required |
---|---|---|---|
message | String | The message | true |
Example:
{
"type": "message",
"message": "This is a message!"
}
Not enough quiz types? Let's create your own plugin and define your own quiz types!
A plugin is a folder containing at least one file: a configuration file extension.json
.
A plugin that has only one file (extension.json
) cannot register quiz types.
If you want to register quiz types (why else would you create a plugin?), you must have at least one Python file,
which is linked in the files
array of the configuration file.
The builtin quiz types are defined by the default
plugin.
Here is a step-by-step guide:
-
Create a folder that should ideally have the name of the plugin. You mustn't do that, but it's more comfortable and clear.
-
Create the plugin main file, which is a Python file (
.py
). -
Copy the following template inside a new
extension.json
file, which is in the main folder:{ "id": "", "files": [] }
The
files
field is a list of python files (relativ from plugin folder) that are executed on loading plugin. -
Fill the name and the id. The id should be unique!
-
Create a new python file in the main folder and specify it in the
files
field of theextension.json
file. -
Fill the referenced Python files with your plugin content! When you create quiz types, you need to have a plugin object.
Create it like this:
from quiz_enchanter import Plugin plugin = Plugin("id", "Name")
The id needs to be the id from the config file. When you need this plugin in another file to register more quiz types, you can use
Plugin.get_plugin("id")
, where id is your plugin's id.There are two ways to register quiz types:
-
Create quiz types and use their decorators.
quiz_type = plugin.quiz_type("id", "Name")
creates an empty quiz type. To register model or command-line interfaces, use their decorators. They are calledmodel
andcli
. This is more comfortable than the other option. -
The other way is to use
plugin.register_quiz_type(id, name, model=your_model, cli=your_cli)
.
-
The model is the manager for user input. It manages whether the user's answer is correct and how many points they got.
Methods:
__init__
: It expects one argument: a dict filled with the quiz JSON data from the quiz file.property is_correct
: Returns a tuple of two ints: The reached points and the max points the user could reach. This method shouldn't get user inputs! Default is 0, 0.
If you don't create a model class,
the cli
's model
parameter will be a dict (actually it's a DictModel, which inherits from dict),
filled with information from the JSON file.
The CLI gets input from the user using print
s and inputs
s.
The CLI shouldn't print whether the user's input is correct or false!
Arguments:
model
: The model, already initialised with the quiz JSON data.
Returns the user's selection.
After registration, you can use your quiz type in quiz files.
Set the type
to your quiz type's id and fill the other parameters for your quiz type.
This example plugin can be found under the name example_plugin
in the quizzes
folder.
This example plugin has the following structure:
example_plugin/
extension.json
example.py
The extension.json
has the following content:
{
"name": "Example Plugin!",
"id": "example",
"files": ["example.py"]
}
example.py
:
from quiz_enchanter import Plugin, BaseModel
plugin = Plugin("example", "Example plugin") # The id must match the id from the config file
example_quiz_type = plugin.quiz_type("example", "Example quiz type")
@example_quiz_type.model
class ExampleModel(BaseModel):
def __init__(self, json_data):
self.question = json_data["question"]
def is_correct(self, selection):
return 1, 1
@example_quiz_type.cli
def run(model):
input(model.question)
If you need more examples, take a look at the default
plugin.
To test our plugin, we need to create a quiz file.
Since there are plugins needed for the quiz, we need to combine our plugin and the quiz file.
So, create a folder, which name is the id of our quiz, and place the quiz file inside.
The quiz file must be named quiz.json
.
Next to quiz.json
, we need to create a folder plugins
and place our plugin inside it.
Then start the QuizEnchanter.py and write example
!
If you want, create more complex quizzes and plugins!
Good luck!