diff --git a/demo-notebooks/demo08-quiz.py b/demo-notebooks/demo08-quiz.py
index 0e0a66be..8f463e3f 100644
--- a/demo-notebooks/demo08-quiz.py
+++ b/demo-notebooks/demo08-quiz.py
@@ -28,7 +28,7 @@
# ---
# %% [markdown]
-# # some quizzes
+# # one sample quiz
# %% {"scrolled": true}
# mostly for using under binder or in a devel tree
@@ -41,17 +41,7 @@
# %autoreload 2
# %% [markdown]
-# ## a quizz is made of questions
-
-# %% [markdown]
-# a Quiz object contains one or several questions; here is an example with a single question
-
-# %% {"scrolled": false}
-from exercises.quizsample import single_quiz
-single_quiz.widget()
-
-# %% [markdown]
-# ## more questions
+# ## a quiz is made of questions
#
# in this notebook the correct answers are always the one starting with 'a'
@@ -65,5 +55,5 @@
# %% [markdown]
# Here's the code that defines the above quizz
-# %% {"scrolled": true}
+# %% {"scrolled": false}
# !cat ../exercises/quizsample.py
diff --git a/demo-notebooks/demo09-quiz2.py b/demo-notebooks/demo09-quiz2.py
new file mode 100644
index 00000000..635c3aac
--- /dev/null
+++ b/demo-notebooks/demo09-quiz2.py
@@ -0,0 +1,60 @@
+# ---
+# jupyter:
+# jupytext:
+# cell_metadata_filter: all
+# cell_metadata_json: true
+# formats: py:percent
+# notebook_metadata_filter: all,-language_info,-jupytext.text_representation.jupytext_version
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# kernelspec:
+# display_name: Python 3
+# language: python
+# name: python3
+# toc:
+# base_numbering: 1
+# nav_menu: {}
+# number_sections: true
+# sideBar: true
+# skip_h1_title: false
+# title_cell: Table of Contents
+# title_sidebar: Contents
+# toc_cell: false
+# toc_position: {}
+# toc_section_display: true
+# toc_window_display: false
+# ---
+
+# %% [markdown]
+# # another quiz
+
+# %% {"scrolled": true}
+# mostly for using under binder or in a devel tree
+import sys
+sys.path.append('..')
+
+# %% {"scrolled": true}
+# for convenience in development
+# %load_ext autoreload
+# %autoreload 2
+
+# %% [markdown]
+# ## a quizz is made of questions
+
+# %% [markdown]
+# a Quiz object contains one or several questions; here is an example with a single question
+
+# %% {"scrolled": false}
+from exercises.quizsample2 import quiz2
+quiz2.widget()
+
+# %% [markdown]
+# ## under the hood
+
+# %% [markdown]
+# Here's the code that defines the above quizz
+
+# %% {"scrolled": false}
+# !cat ../exercises/quizsample2.py
diff --git a/exercises/quizsample.py b/exercises/quizsample.py
index a1b08e26..c238e958 100644
--- a/exercises/quizsample.py
+++ b/exercises/quizsample.py
@@ -1,22 +1,5 @@
from nbautoeval import Quiz, QuizQuestion, Option, CodeOption, MathOption
-###
-# most basic single-answer
-
-question_basic_single = QuizQuestion(
- "Pick the right fruit\n(one correct option)",
- options=[
- Option("banana"),
- Option("pear"),
- Option("apple", correct=True),
- ],
- horizontal=True,
-)
-single_quiz = Quiz(
- "quizsample-single",
- [question_basic_single])
-
-
questions = []
###
question_basic_multiple = QuizQuestion(
@@ -30,7 +13,7 @@
Option("pineapple"),
],
score = 1,
- horizontal=True,
+ horizontal_layout=True,
)
questions.append(question_basic_multiple)
@@ -46,7 +29,7 @@
],
shuffle=False,
score = 2,
- horizontal=True,
+ horizontal_layout=True,
)
questions.append(question_unshuffle)
@@ -65,7 +48,7 @@
MathOption(r"multiple double dollars $$\forall x\in\mathbb{R}$$ $$\forall x\in\mathbb{R}$$ $$\forall x\in\mathbb{R}$$"),
],
score = 3,
- horizontal=True,
+ horizontal_layout=True,
)
questions.append(question_math)
@@ -78,7 +61,8 @@
Option("pear"),
],
score = 4,
- horizontal=True,
+ horizontal_layout=True,
+ horizontal_options=True,
)
questions.append(question_none)
@@ -93,7 +77,7 @@
CodeOption("b = sort(x for x in list if x.is_valid())"),
],
score = 5,
- horizontal=True,
+ horizontal_options=True,
)
questions.append(question_code)
diff --git a/exercises/quizsample2.py b/exercises/quizsample2.py
new file mode 100644
index 00000000..b993e4aa
--- /dev/null
+++ b/exercises/quizsample2.py
@@ -0,0 +1,58 @@
+from nbautoeval import Quiz, QuizQuestion, Option, CodeOption, MathOption
+
+
+############
+quiz2 = Quiz(
+
+ # needs a unique name for storing progress and marks
+ "quizsample-horizontal",
+
+ [
+ QuizQuestion("""
+horizontal_layout means to have
+
the questions and the options
+
in a horizontal box""",
+ options=[
+ Option('', correct=True),
+ Option('
'),
+ ],
+ horizontal_layout=True,
+ ),
+
+
+ QuizQuestion("""
+horizontal_options means the options appear side by side like here,
+because horizontal_layout is False the question spans 100% of page width
+""",
+ options=[
+ Option('
', correct=True),
+ Option('
'),
+ ],
+ horizontal_options=True,
+ ),
+
+
+ QuizQuestion("""
+the default is to have none of these 2 horizontal flags
+""",
+ options=[
+ Option('
', correct=True),
+ Option('
'),
+ ],
+ ),
+
+ QuizQuestion("""
+of course they can be used together as well""",
+ options=[
+ Option('
', correct=True),
+ Option('
'),
+ ],
+ horizontal_layout=True,
+ horizontal_options=True,
+ ),
+
+
+ ],
+ max_attempts = 5,
+ )
+
diff --git a/media/image1.png b/media/image1.png
new file mode 100644
index 00000000..e68a9bea
Binary files /dev/null and b/media/image1.png differ
diff --git a/media/image2.png b/media/image2.png
new file mode 100644
index 00000000..a899de4b
Binary files /dev/null and b/media/image2.png differ
diff --git a/nbautoeval/quiz.py b/nbautoeval/quiz.py
index 465dd0bc..0c9e5539 100644
--- a/nbautoeval/quiz.py
+++ b/nbautoeval/quiz.py
@@ -47,7 +47,7 @@ def __iter__(self):
# usually options are displayed in some random order
class _DisplayedOptionsList:
- def __init__(self, options: List[GenericBooleanOption], shuffle=True):
+ def __init__(self, options: List[GenericBooleanOption], shuffle):
self.displayed = options[:]
if shuffle:
random.shuffle(self.displayed)
@@ -126,6 +126,11 @@ def __iter__(self):
}
"""
+def points(score):
+ return f"{score} {'pt' if score<=1 else 'pts'}"
+
+
+
class QuizQuestion:
"""
question may include html tags and/or math content between '$$'
@@ -144,12 +149,15 @@ class QuizQuestion:
def __init__(self, question: str, options: List,
*,
score = 1,
- shuffle=True, horizontal=False):
+ shuffle=True,
+ horizontal_layout=False,
+ horizontal_options=False):
self.question = question
self.options_list = _OptionsList(options)
- self.displayed = _DisplayedOptionsList(options)
+ self.displayed = _DisplayedOptionsList(options, shuffle)
self.score = score
- self.horizontal = horizontal
+ self.horizontal_layout = horizontal_layout
+ self.horizontal_options = horizontal_options
self.feedback_area = None
self._widget_instance = None
@@ -159,8 +167,7 @@ def widget(self):
if self._widget_instance:
return self._widget_instance
- points = f"{self.score} {'pt' if self.score<=1 else 'pts'}"
- points_question = f'