@lernapps/app-templates 0.0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +195 -2
- package/dist/appname-Bh23cUuz.mjs +12 -0
- package/dist/assessment-Dy359O1O.mjs +1696 -0
- package/dist/block-BK_ohsH1.mjs +82 -0
- package/dist/blocks-CxtCPAa5.mjs +149 -0
- package/dist/blocks.mjs +4 -0
- package/dist/check-CteIFN96.mjs +254 -0
- package/dist/content-DO6oEJxj.mjs +140 -0
- package/dist/contract-PONpxJtd.mjs +52 -0
- package/dist/e2e-CU0n_unV.mjs +89 -0
- package/dist/engine-CArxqizW.mjs +136 -0
- package/dist/explainer-e2e.mjs +1311 -0
- package/dist/explainer-islands.mjs +197 -0
- package/dist/explainer-plugin.mjs +2132 -0
- package/dist/explainer.mjs +1246 -0
- package/dist/html-mffkHGHh.mjs +89 -0
- package/dist/image-CspJVfyQ.mjs +21 -0
- package/dist/interactive-e2e.mjs +140 -0
- package/dist/interactive-plugin.mjs +242 -0
- package/dist/interactive.mjs +75 -0
- package/dist/load-RosvaPZf.mjs +16976 -0
- package/dist/needs-BzEahJ6X.mjs +97 -0
- package/dist/pages-9RaaomoO.mjs +81 -0
- package/dist/questions-e2e.mjs +1 -0
- package/dist/questions-engine.mjs +3 -0
- package/dist/questions.mjs +6 -0
- package/dist/quiz-DnW-xtCh.mjs +70 -0
- package/dist/quiz-e2e.mjs +174 -0
- package/dist/quiz-plugin.mjs +266 -0
- package/dist/quiz.mjs +246 -0
- package/dist/render-D5kwkNt1.mjs +507 -0
- package/dist/render-DqHOJyHK.mjs +146 -0
- package/dist/render-GS1Htlu8.mjs +545 -0
- package/dist/result-D_mmCVwN.mjs +180 -0
- package/dist/tasks-DADUYy52.mjs +74 -0
- package/dist/validate-BDwL7Su3.mjs +1076 -0
- package/dist/validate-Bxy9NfB8.mjs +146 -0
- package/dist/vue-DO1m6q1R.mjs +40 -0
- package/dist/vue-code-BkJjW_I_.mjs +320 -0
- package/docs/arc42/01-introduction-and-goals.arc42.md +82 -0
- package/docs/arc42/02-constraints.arc42.md +228 -0
- package/docs/arc42/03-system-context.arc42.md +118 -0
- package/docs/arc42/04-solution-strategy.arc42.md +47 -0
- package/docs/arc42/05-building-blocks.arc42.md +307 -0
- package/docs/arc42/06-runtime-view.arc42.md +98 -0
- package/docs/arc42/07-deployment-view.arc42.md +160 -0
- package/docs/arc42/08-concepts.arc42.md +123 -0
- package/docs/arc42/09-decisions.arc42.md +246 -0
- package/docs/arc42/10-quality-requirements.arc42.md +155 -0
- package/docs/arc42/11-risks.arc42.md +113 -0
- package/docs/arc42/12-glossary.arc42.md +162 -0
- package/docs/arc42/architecture-evidence.md +395 -0
- package/explainer/.arc42ignore +3 -0
- package/explainer/README.md +54 -0
- package/explainer/_gitignore +5 -0
- package/explainer/docs/arc42/03-explainer-system-context.arc42.md +35 -0
- package/explainer/docs/arc42/05-explainer-building-blocks.arc42.md +659 -0
- package/explainer/docs/arc42/06-explainer-runtime-view.arc42.md +105 -0
- package/explainer/docs/arc42/07-explainer-deployment-view.arc42.md +34 -0
- package/explainer/docs/arc42/08-explainer-concepts.arc42.md +17 -0
- package/explainer/docs/arc42/09-explainer-decisions.arc42.md +443 -0
- package/explainer/docs/arc42/10-explainer-quality-requirements.arc42.md +54 -0
- package/explainer/docs/arc42/11-explainer-risks.arc42.md +17 -0
- package/explainer/docs/arc42/12-explainer-glossary.arc42.md +185 -0
- package/explainer/e2e/explainer.e2e.ts +3 -0
- package/explainer/index.html +11 -0
- package/explainer/package.json +18 -0
- package/explainer/playwright.config.ts +1 -0
- package/explainer/src/app.yaml +20 -0
- package/explainer/src/components/ProzentFeld.test.ts +30 -0
- package/explainer/src/components/ProzentFeld.ts +121 -0
- package/explainer/src/components/ProzentFeld.vue +84 -0
- package/explainer/src/images/hunderterfeld-klammern.svg +105 -0
- package/explainer/src/main.ts +4 -0
- package/explainer/src/prozent/chapter.yaml +18 -0
- package/explainer/src/prozent/grundwert.yaml +115 -0
- package/explainer/src/prozent/prozentsatz.yaml +99 -0
- package/explainer/src/prozent/prozentwert.yaml +119 -0
- package/explainer/tsconfig.json +1 -0
- package/explainer/vite.config.ts +4 -0
- package/interactive/.arc42ignore +5 -0
- package/interactive/README.md +28 -0
- package/interactive/_gitignore +4 -0
- package/interactive/docs/arc42/05-interactive-building-blocks.arc42.md +518 -0
- package/interactive/docs/arc42/06-interactive-runtime-view.arc42.md +58 -0
- package/interactive/docs/arc42/07-interactive-deployment-view.arc42.md +35 -0
- package/interactive/docs/arc42/08-interactive-concepts.arc42.md +52 -0
- package/interactive/docs/arc42/09-interactive-decisions.arc42.md +130 -0
- package/interactive/docs/arc42/10-interactive-quality-requirements.arc42.md +45 -0
- package/interactive/docs/arc42/11-interactive-risks.arc42.md +20 -0
- package/interactive/docs/arc42/12-interactive-glossary.arc42.md +80 -0
- package/interactive/e2e/interactive.e2e.ts +3 -0
- package/interactive/index.html +11 -0
- package/interactive/package.json +18 -0
- package/interactive/playwright.config.ts +1 -0
- package/interactive/src/app.yaml +28 -0
- package/interactive/src/core/index.ts +101 -0
- package/interactive/src/data/lessons.json +4 -0
- package/interactive/src/env.d.ts +6 -0
- package/interactive/src/main.ts +6 -0
- package/interactive/src/messages/de.json +12 -0
- package/interactive/src/playthroughs/grundreihe.yaml +33 -0
- package/interactive/src/playthroughs/obere-reihe.yaml +14 -0
- package/interactive/src/ui/App.vue +85 -0
- package/interactive/tsconfig.json +1 -0
- package/interactive/vite.config.ts +4 -0
- package/package.json +143 -4
- package/quiz/README.md +31 -0
- package/quiz/_gitignore +5 -0
- package/quiz/docs/arc42/05-quiz-building-blocks.arc42.md +283 -0
- package/quiz/docs/arc42/06-quiz-runtime-view.arc42.md +21 -0
- package/quiz/docs/arc42/07-quiz-deployment-view.arc42.md +33 -0
- package/quiz/docs/arc42/09-quiz-decisions.arc42.md +36 -0
- package/quiz/docs/arc42/10-quiz-quality-requirements.arc42.md +53 -0
- package/quiz/docs/arc42/11-quiz-risks.arc42.md +19 -0
- package/quiz/docs/arc42/12-quiz-glossary.arc42.md +27 -0
- package/quiz/e2e/quiz.e2e.ts +3 -0
- package/quiz/index.html +11 -0
- package/quiz/package.json +18 -0
- package/quiz/playwright.config.ts +1 -0
- package/quiz/src/images/berge-ordnen.jpg +0 -0
- package/quiz/src/images/everest-hoehe.jpg +0 -0
- package/quiz/src/images/galapagos.jpg +0 -0
- package/quiz/src/images/grand-canyon.jpg +0 -0
- package/quiz/src/images/totes-meer.jpg +0 -0
- package/quiz/src/images/uluru.jpg +0 -0
- package/quiz/src/images/wasserfaelle-laender.jpg +0 -0
- package/quiz/src/main.ts +4 -0
- package/quiz/src/quiz.json +312 -0
- package/quiz/tsconfig.json +1 -0
- package/quiz/vite.config.ts +4 -0
- package/runtime/explainer/assessment-client.ts +478 -0
- package/runtime/explainer/assessment-page.ts +448 -0
- package/runtime/explainer/assessment.ts +393 -0
- package/runtime/explainer/check-page.ts +520 -0
- package/runtime/explainer/components/exercise.ts +409 -0
- package/runtime/explainer/components/props.ts +230 -0
- package/runtime/explainer/components/read.ts +428 -0
- package/runtime/explainer/content.ts +277 -0
- package/runtime/explainer/e2e.ts +1488 -0
- package/runtime/explainer/exercises.ts +326 -0
- package/runtime/explainer/explainer.css +1283 -0
- package/runtime/explainer/explainer.ts +838 -0
- package/runtime/explainer/explainer.v1.schema.json +1165 -0
- package/runtime/explainer/expression.ts +407 -0
- package/runtime/explainer/fraction.ts +107 -0
- package/runtime/explainer/generated/comparator.ts +31 -0
- package/runtime/explainer/generated/question.ts +165 -0
- package/runtime/explainer/generated/soundness.ts +280 -0
- package/runtime/explainer/generated/texts.ts +257 -0
- package/runtime/explainer/generated/types.ts +103 -0
- package/runtime/explainer/generated/values.ts +136 -0
- package/runtime/explainer/islands.ts +281 -0
- package/runtime/explainer/load.ts +457 -0
- package/runtime/explainer/messages/de.json +200 -0
- package/runtime/explainer/messages/en.json +200 -0
- package/runtime/explainer/messages.ts +13 -0
- package/runtime/explainer/needs.ts +122 -0
- package/runtime/explainer/open-task.ts +235 -0
- package/runtime/explainer/outline.ts +306 -0
- package/runtime/explainer/plugin.ts +488 -0
- package/runtime/explainer/position.ts +62 -0
- package/runtime/explainer/prompt.ts +75 -0
- package/runtime/explainer/render.ts +686 -0
- package/runtime/explainer/result.ts +238 -0
- package/runtime/explainer/routes.ts +119 -0
- package/runtime/explainer/schema.ts +140 -0
- package/runtime/explainer/scope.ts +87 -0
- package/runtime/explainer/stuck.ts +57 -0
- package/runtime/explainer/tasks.ts +109 -0
- package/runtime/explainer/tutor.ts +469 -0
- package/runtime/explainer/tutorpage.ts +669 -0
- package/runtime/explainer/video.ts +123 -0
- package/runtime/interactive/contract.ts +121 -0
- package/runtime/interactive/e2e.ts +190 -0
- package/runtime/interactive/interactive.css +82 -0
- package/runtime/interactive/interactive.ts +115 -0
- package/runtime/interactive/interactive.v1.schema.json +146 -0
- package/runtime/interactive/load.ts +188 -0
- package/runtime/interactive/messages/de.json +14 -0
- package/runtime/interactive/messages/en.json +14 -0
- package/runtime/interactive/messages.ts +11 -0
- package/runtime/interactive/playthrough.v1.schema.json +143 -0
- package/runtime/interactive/plugin.ts +266 -0
- package/runtime/interactive/render.ts +126 -0
- package/runtime/quiz/e2e.ts +233 -0
- package/runtime/quiz/engine.ts +242 -0
- package/runtime/quiz/messages/de.json +23 -0
- package/runtime/quiz/messages/en.json +23 -0
- package/runtime/quiz/plugin.ts +150 -0
- package/runtime/quiz/quiz.css +154 -0
- package/runtime/quiz/quiz.ts +56 -0
- package/runtime/quiz/quiz.v1.schema.json +72 -0
- package/runtime/quiz/render.ts +173 -0
- package/runtime/quiz/validate.ts +108 -0
- package/runtime/shared/appname.ts +16 -0
- package/runtime/shared/blocks/block.ts +162 -0
- package/runtime/shared/blocks/blocks.css +190 -0
- package/runtime/shared/blocks/blocks.v1.schema.json +432 -0
- package/runtime/shared/blocks/code.ts +26 -0
- package/runtime/shared/blocks/figures.ts +49 -0
- package/runtime/shared/blocks/image.ts +25 -0
- package/runtime/shared/blocks/index.ts +13 -0
- package/runtime/shared/blocks/messages/de.json +4 -0
- package/runtime/shared/blocks/messages/en.json +4 -0
- package/runtime/shared/blocks/render.ts +134 -0
- package/runtime/shared/blocks/validate.ts +165 -0
- package/runtime/shared/content.ts +197 -0
- package/runtime/shared/examples.ts +20 -0
- package/runtime/shared/html.ts +10 -0
- package/runtime/shared/languages.ts +94 -0
- package/runtime/shared/page.css +101 -0
- package/runtime/shared/pages.ts +114 -0
- package/runtime/shared/questions/e2e.ts +115 -0
- package/runtime/shared/questions/engine.ts +209 -0
- package/runtime/shared/questions/index.ts +39 -0
- package/runtime/shared/questions/messages/de.json +26 -0
- package/runtime/shared/questions/messages/en.json +26 -0
- package/runtime/shared/questions/question.ts +433 -0
- package/runtime/shared/questions/question.v1.schema.json +346 -0
- package/runtime/shared/questions/questions.css +192 -0
- package/runtime/shared/questions/render.ts +255 -0
- package/runtime/shared/questions/validate.ts +518 -0
- package/runtime/shared/schema.ts +44 -0
- package/runtime/shared/text/check.ts +68 -0
- package/runtime/shared/text/formula.ts +69 -0
- package/runtime/shared/text/markdown.ts +185 -0
- package/runtime/shared/text/speech.ts +39 -0
- package/runtime/shared/text/text.v1.schema.json +34 -0
- package/runtime/shared/vue-code.ts +395 -0
- package/runtime/shared/vue.ts +38 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Risks and Technical Debt
|
|
2
|
+
|
|
3
|
+
The explainer's risks, besides the generic ones.
|
|
4
|
+
|
|
5
|
+
## YouTube's Player After the Click
|
|
6
|
+
|
|
7
|
+
Once the player of youtube-nocookie.com loads, YouTube gets the learner's IP address and may keep data in its own
|
|
8
|
+
frame; the privacy-enhanced host only defers that until the click. The app cannot limit what the player does.
|
|
9
|
+
|
|
10
|
+
```arc42
|
|
11
|
+
:::risk
|
|
12
|
+
id: risk-explainer-video-after-click
|
|
13
|
+
severity: low
|
|
14
|
+
title: After the click, YouTube's player sends data to Google
|
|
15
|
+
mitigation: Nothing loads before the click; the note says what the click sends; the standing choice is the learner's and can be withdrawn; the catalog entry declares thirdParty on-click.
|
|
16
|
+
:::
|
|
17
|
+
```
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Glossary
|
|
2
|
+
|
|
3
|
+
The explainer's terms, besides the generic ones.
|
|
4
|
+
|
|
5
|
+
## Block
|
|
6
|
+
|
|
7
|
+
A page is a list of blocks from a closed set, each with its type; sections give the structure.
|
|
8
|
+
|
|
9
|
+
```arc42
|
|
10
|
+
:::glossary-term
|
|
11
|
+
id: term-block
|
|
12
|
+
title: Block
|
|
13
|
+
definition: One element of an explainer page in its content YAML (a section, a text, a formula, a figure, an exercise, a vue-component, ...).
|
|
14
|
+
:::
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Island
|
|
18
|
+
|
|
19
|
+
Only a page with a component loads Vue.
|
|
20
|
+
|
|
21
|
+
```arc42
|
|
22
|
+
:::glossary-term
|
|
23
|
+
id: term-island
|
|
24
|
+
title: Island
|
|
25
|
+
definition: The place of a Vue component on a static explainer page, rendered at build and hydrated in the browser.
|
|
26
|
+
:::
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Task Number
|
|
30
|
+
|
|
31
|
+
"Aufgabe Nr. n" on the page, `?<id>=<n>` in the address.
|
|
32
|
+
|
|
33
|
+
```arc42
|
|
34
|
+
:::glossary-term
|
|
35
|
+
id: term-task-number
|
|
36
|
+
title: Task number
|
|
37
|
+
definition: The number of one of the distinct tasks of a seeded exercise, shared by the learner, the tutor and the address.
|
|
38
|
+
:::
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Generated Exercise
|
|
42
|
+
|
|
43
|
+
Written as `generated` in the content: given values, preconditions, a task template, an answer and typical mistakes.
|
|
44
|
+
|
|
45
|
+
```arc42
|
|
46
|
+
:::glossary-term
|
|
47
|
+
id: term-generated-exercise
|
|
48
|
+
title: Generated exercise
|
|
49
|
+
definition: An exercise of the explainer drawn from a seed, property-tested at build and live in the browser.
|
|
50
|
+
:::
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Open Task
|
|
54
|
+
|
|
55
|
+
Written as `open-task` in the content. German: offene Aufgabe.
|
|
56
|
+
|
|
57
|
+
```arc42
|
|
58
|
+
:::glossary-term
|
|
59
|
+
id: term-open-task
|
|
60
|
+
title: Open task
|
|
61
|
+
definition: An exercise the learner answers in their own words, typed or on paper with a photo, then compares with the points of a good answer.
|
|
62
|
+
:::
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Point
|
|
66
|
+
|
|
67
|
+
A point of a good answer to an open task, named P1, P2 … in the result and on the tutor page.
|
|
68
|
+
|
|
69
|
+
```arc42
|
|
70
|
+
:::glossary-term
|
|
71
|
+
id: term-point
|
|
72
|
+
title: Point
|
|
73
|
+
definition: One checkable sentence a good answer to an open task has, about its content with the section it comes from, or about its form.
|
|
74
|
+
:::
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Scope
|
|
78
|
+
|
|
79
|
+
`scope` in the content, written at `scope/` beside each page, chapter and the app for the tutor.
|
|
80
|
+
|
|
81
|
+
```arc42
|
|
82
|
+
:::glossary-term
|
|
83
|
+
id: term-scope
|
|
84
|
+
title: Scope
|
|
85
|
+
definition: The whole learning path of an explainer in the creator's own words, page by page, with what belongs to it and what does not; for the tutor, never shown to the learner.
|
|
86
|
+
:::
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Tutor Page
|
|
90
|
+
|
|
91
|
+
`<chapter>/<page>/tutor/`, the address a tutor's prompt names for a page.
|
|
92
|
+
|
|
93
|
+
```arc42
|
|
94
|
+
:::glossary-term
|
|
95
|
+
id: term-tutor-page
|
|
96
|
+
title: Tutor page
|
|
97
|
+
definition: The one source of what the learner's own AI assistant gets about one content page: who it helps and how it guides, where the child is, then the page's content and its exercises with every task number, a generated one with its table of tasks; its query says where the learner is.
|
|
98
|
+
:::
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Table of Tasks
|
|
102
|
+
|
|
103
|
+
The inputs and outputs of each task number of a `generated` exercise on the tutor page, one line each:
|
|
104
|
+
`27 | 15 | 1260 | 189 | 18900` under `Nr. | p | G | Lösung | F1`.
|
|
105
|
+
|
|
106
|
+
```arc42
|
|
107
|
+
:::glossary-term
|
|
108
|
+
id: term-table-of-tasks
|
|
109
|
+
title: Table of tasks
|
|
110
|
+
definition: For each task number of a generated exercise, or of an exercise component that declares it, under its template on the tutor page: the values of its placeholders, the solution and what each typical mistake gives, worked out, so that the tutor fills in and calculates nothing.
|
|
111
|
+
:::
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Way to the Tutor
|
|
115
|
+
|
|
116
|
+
How the learner reaches the tutor: A, "Mit <name> lernen", for a page; B, "Hilfe", for one task.
|
|
117
|
+
|
|
118
|
+
```arc42
|
|
119
|
+
:::glossary-term
|
|
120
|
+
id: term-tutor-way
|
|
121
|
+
title: Way to the tutor
|
|
122
|
+
definition: Once an assistant is switched on, "Mit <name> lernen" (A) opens it with one sentence that names the page's tutor page with where the learner is; "Hilfe", "Warum?" after a wrong answer (B), gives the lines of one task, as a new chat (B1) or, on a page a tutor opened, copied for the running chat (B2).
|
|
123
|
+
:::
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Assistant Switched On
|
|
127
|
+
|
|
128
|
+
The learner's choice of a KI assistant, on the start page or beside the title of a page.
|
|
129
|
+
|
|
130
|
+
```arc42
|
|
131
|
+
:::glossary-term
|
|
132
|
+
id: term-tutor-assistant
|
|
133
|
+
title: Assistant switched on
|
|
134
|
+
definition: One of the app's assistants, or copying the text, chosen once by the learner and kept on the device per app; while one is on, each content page has the bar of way A and every exercise the help button of way B.
|
|
135
|
+
:::
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Need
|
|
139
|
+
|
|
140
|
+
What helps a learner when the tutor talks to them, named by what helps, never by a diagnosis.
|
|
141
|
+
|
|
142
|
+
```arc42
|
|
143
|
+
:::glossary-term
|
|
144
|
+
id: term-tutor-need
|
|
145
|
+
title: Need
|
|
146
|
+
definition: One of the ways the tutor can talk that a learner chooses, none, one or several, for every explainer or for one app (kurze-schritte, wenig-lesen, mehr-tiefe, andere-muttersprache, klar-und-woertlich, rechnen-anschaulich); the tutor page's query names them in bedarf=, and the tutor page holds a short section for each.
|
|
147
|
+
:::
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Lines of "Hilfe"
|
|
151
|
+
|
|
152
|
+
What way B gives the tutor about one task.
|
|
153
|
+
|
|
154
|
+
```arc42
|
|
155
|
+
:::glossary-term
|
|
156
|
+
id: term-stuck-lines
|
|
157
|
+
title: Lines of "Hilfe"
|
|
158
|
+
definition: In the learner's voice: the page's tutor page with the page's task numbers, uebung and abschnitt, and the task; the last wrong input with its tries, the app's message for it word for word, the hint or solution opened; no rule for the tutor.
|
|
159
|
+
:::
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Result Line
|
|
163
|
+
|
|
164
|
+
What "Zurück" at one task copies for the learner to paste into the chat; "Zurück zum Tutor" copies the tutor page and a
|
|
165
|
+
line like it for each task of the session.
|
|
166
|
+
|
|
167
|
+
```arc42
|
|
168
|
+
:::glossary-term
|
|
169
|
+
id: term-result-line
|
|
170
|
+
title: Result line
|
|
171
|
+
definition: The exercise, its task number, how far the learner got and the last input, with the absolute address of the page's tutor page with where the learner is.
|
|
172
|
+
:::
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Self-Assessment
|
|
176
|
+
|
|
177
|
+
German: Selbsteinschätzung. Optional, for the app or a chapter.
|
|
178
|
+
|
|
179
|
+
```arc42
|
|
180
|
+
:::glossary-term
|
|
181
|
+
id: term-self-assessment
|
|
182
|
+
title: Self-assessment
|
|
183
|
+
definition: Exercises of an explainer's content pages, a few per page of its own, which the learner may answer before learning and which are checked only all together; the result says per content page whether it is probably known, to look at again or to read.
|
|
184
|
+
:::
|
|
185
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "explainer",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vp dev",
|
|
7
|
+
"build": "vp build --outDir _site",
|
|
8
|
+
"check": "lernapps check"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@lernapps/app-templates": "file:..",
|
|
12
|
+
"@lernapps/tooling": "^0.1.2",
|
|
13
|
+
"vite-plus": "1.4.0"
|
|
14
|
+
},
|
|
15
|
+
"overrides": {
|
|
16
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "@lernapps/tooling/playwright";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../node_modules/@lernapps/app-templates/runtime/explainer/explainer.v1.schema.json
|
|
2
|
+
title: Prozentrechnung
|
|
3
|
+
intro: |
|
|
4
|
+
Prozentwert, Prozentsatz und Grundwert: Was sie bedeuten, wie du sie ausrechnest, und je ein Beispiel dazu.
|
|
5
|
+
Für die Klassen 7 und 8.
|
|
6
|
+
languages: [de]
|
|
7
|
+
chapters: [prozent]
|
|
8
|
+
sources:
|
|
9
|
+
- title: Prozentrechnung mittels Formeln (Serlo)
|
|
10
|
+
url: https://de.serlo.org/mathe/2193/prozentrechnung-mittels-formeln
|
|
11
|
+
scope:
|
|
12
|
+
text: |
|
|
13
|
+
Die App führt in die Prozentrechnung ein. Sie geht von drei Größen aus: dem Grundwert $G$ (das Ganze, 100 %), dem
|
|
14
|
+
Prozentsatz $p\,\%$ (welcher Anteil gemeint ist) und dem Prozentwert $W$ (der Teil, in der Einheit des Ganzen). Jede
|
|
15
|
+
Seite nimmt eine der drei Größen als die gesuchte und zeigt, wie man sie aus den beiden anderen ausrechnet. Der Weg
|
|
16
|
+
über 1 % hilft auf allen drei Seiten: Das Ganze geteilt durch 100 ist 1 %.
|
|
17
|
+
out:
|
|
18
|
+
- "Zinsen und Zinseszins"
|
|
19
|
+
- "Prozentpunkte und die Veränderung eines Prozentsatzes"
|
|
20
|
+
- "vermehrter und verminderter Grundwert (Preis mit Aufschlag oder nach Rabatt in einem Schritt)"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { expect, test } from "vite-plus/test";
|
|
2
|
+
import { check, describe, generate, mistakes, reason, solution, wrong } from "./ProzentFeld.ts";
|
|
3
|
+
|
|
4
|
+
const props = {
|
|
5
|
+
task: "Das Feld hat {G} Kästchen. Färbe {p} % davon.",
|
|
6
|
+
mistakes: ["{p} Kästchen sind {p} % von 100.", "Das ist der Rest."],
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
test("p % of the field is right; p squares and the rest are wrong", () => {
|
|
10
|
+
for (let seed = 1; seed <= 50; seed++) {
|
|
11
|
+
const task = generate(seed, props);
|
|
12
|
+
expect([20, 25, 40, 50]).toContain(task.G);
|
|
13
|
+
expect(Number.isInteger((task.G * task.p) / 100)).toBe(true);
|
|
14
|
+
expect(check(task, solution(task))).toBe(true);
|
|
15
|
+
expect(check(task, wrong(task))).toBe(false);
|
|
16
|
+
for (const answer of mistakes(task)) if (answer !== undefined) expect(check(task, answer)).toBe(false);
|
|
17
|
+
expect(new Set(mistakes(task)).size).toBe(2);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("describe fills in the task; each typical mistake gets its message", () => {
|
|
22
|
+
const task = { G: 20, p: 15 };
|
|
23
|
+
expect(describe(task, props, "de")).toEqual({
|
|
24
|
+
task: "Das Feld hat 20 Kästchen. Färbe 15 % davon.",
|
|
25
|
+
solution: "3 Kästchen: 20 · 15 : 100 = 3",
|
|
26
|
+
});
|
|
27
|
+
expect(reason(task, 15, props)).toBe("15 Kästchen sind 15 % von 100.");
|
|
28
|
+
expect(reason(task, 17, props)).toBe("Das ist der Rest.");
|
|
29
|
+
expect(reason(task, 4, props)).toBeUndefined();
|
|
30
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// The logic of ProzentFeld.vue, a field of G squares, together 100 %, of which the learner colours p %: pure
|
|
2
|
+
// functions, which the build tests over fixed seeds (the exercise contract). A task is G and p; an answer is the
|
|
3
|
+
// number of squares coloured, whichever they are. The explainer checks an answer with check and gives the message of
|
|
4
|
+
// reason. describe states a task and its solution, about what the exercise is; template, params, mistakes and show give
|
|
5
|
+
// a tutor the task once and each number's inputs and outputs.
|
|
6
|
+
|
|
7
|
+
/** The props the logic needs: the task with {G} and {p}, and the app's message for each typical mistake. */
|
|
8
|
+
export interface Props {
|
|
9
|
+
task: string;
|
|
10
|
+
mistakes?: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Task {
|
|
14
|
+
/** The number of squares, the whole: 100 %. */
|
|
15
|
+
G: number;
|
|
16
|
+
/** The percentage to colour. */
|
|
17
|
+
p: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** The number of squares coloured. */
|
|
21
|
+
export type Answer = number;
|
|
22
|
+
|
|
23
|
+
/** The sizes of the field: never 100, so that p squares is a mistake. */
|
|
24
|
+
const SIZES = [20, 25, 40, 50];
|
|
25
|
+
|
|
26
|
+
/** A small seeded random generator (mulberry32). */
|
|
27
|
+
function random(seed: number): () => number {
|
|
28
|
+
let state = seed >>> 0;
|
|
29
|
+
return () => {
|
|
30
|
+
state = (state + 0x6d2b79f5) >>> 0;
|
|
31
|
+
let t = state;
|
|
32
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
33
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
34
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** The squares p % of the field are. */
|
|
39
|
+
const part = (task: Task) => (task.G * task.p) / 100;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The percentages of a field of `G` squares: whole squares, neither 50 % (the rest would be as many) nor a p whose
|
|
43
|
+
* rest is p squares (the two mistakes would give the same answer).
|
|
44
|
+
*/
|
|
45
|
+
const percentages = (G: number) =>
|
|
46
|
+
Array.from({ length: 99 }, (_, i) => i + 1).filter(
|
|
47
|
+
(p) => Number.isInteger((G * p) / 100) && p !== 50 && G - (G * p) / 100 !== p,
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
/** The task of `seed`: a size and a percentage of it. */
|
|
51
|
+
export function generate(seed: number, _props?: Props): Task {
|
|
52
|
+
const next = random(seed);
|
|
53
|
+
const G = SIZES[Math.floor(next() * SIZES.length)] ?? 20;
|
|
54
|
+
const choices = percentages(G);
|
|
55
|
+
return { G, p: choices[Math.floor(next() * choices.length)] ?? 10 };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Whether `answer` squares are p % of the field. */
|
|
59
|
+
export function check(task: Task, answer: Answer): boolean {
|
|
60
|
+
return answer === part(task);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The right answer. */
|
|
64
|
+
export function solution(task: Task): Answer {
|
|
65
|
+
return part(task);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** A wrong answer: the rest coloured. */
|
|
69
|
+
export function wrong(task: Task): Answer {
|
|
70
|
+
return task.G - part(task);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** The answer of each typical mistake of about.mistakes: p squares (none when p is more than the field), the rest. */
|
|
74
|
+
export function mistakes(task: Task): (Answer | undefined)[] {
|
|
75
|
+
return [task.p < task.G ? task.p : undefined, wrong(task)];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** A text of the props with {G}, {p} and {n} filled in. */
|
|
79
|
+
export const fill = (text: string, task: Task, n = 0) =>
|
|
80
|
+
text.replace(/\{G\}/g, String(task.G)).replace(/\{p\}/g, String(task.p)).replace(/\{n\}/g, String(n));
|
|
81
|
+
|
|
82
|
+
/** The app's message for a wrong answer, from the props: that of its typical mistake, or none. */
|
|
83
|
+
export function reason(task: Task, answer: Answer, props: Props, _lang?: string): string | undefined {
|
|
84
|
+
const index = mistakes(task).findIndex((mistaken) => mistaken === answer);
|
|
85
|
+
const message = index < 0 ? undefined : props.mistakes?.[index];
|
|
86
|
+
return message === undefined ? undefined : fill(message, task, answer);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The task as a learner sees it, and its solution. */
|
|
90
|
+
export function describe(task: Task, props: Props, _lang: string): { task: string; solution: string } {
|
|
91
|
+
return {
|
|
92
|
+
task: fill(props.task, task),
|
|
93
|
+
solution: `${show(part(task))}: ${task.G} · ${task.p} : 100 = ${part(task)}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** The task as a learner reads it, with {G} and {p}: the prop task. */
|
|
98
|
+
export function template(props: Props, _lang: string): string {
|
|
99
|
+
return props.task;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** What sets a task: the size of the field and the percentage. */
|
|
103
|
+
export function params(task: Task, _props: Props, _lang: string): Record<string, number> {
|
|
104
|
+
return { G: task.G, p: task.p };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** An answer as text. */
|
|
108
|
+
export function show(answer: Answer, _task?: Task, _props?: Props, _lang?: string): string {
|
|
109
|
+
return `${answer} Kästchen`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** What the exercise is, for a tutor. */
|
|
113
|
+
export const about = {
|
|
114
|
+
task: "Ein Feld aus G Kästchen ist das Ganze, also 100 %. Das Kind färbt durch Antippen p % davon und drückt „Prüfen“ unter dem Feld. Wie das Hunderterfeld, nur hat das Feld nicht 100 Kästchen.",
|
|
115
|
+
answer: "Die Zahl der gefärbten Kästchen; welche es sind, ist egal.",
|
|
116
|
+
correct: "Richtig, wenn genau G · p : 100 Kästchen gefärbt sind.",
|
|
117
|
+
mistakes: [
|
|
118
|
+
"p Kästchen gefärbt, als hätte das Feld 100 Kästchen.",
|
|
119
|
+
"Den Rest gefärbt: die Kästchen, die nicht zu den p % gehören.",
|
|
120
|
+
],
|
|
121
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// A field of G squares, together 100 %, of which the learner colours p % by tapping, for the task of the number seed.
|
|
3
|
+
// Its logic is in ProzentFeld.ts. It is the input of the task: it emits the number of squares coloured with answer,
|
|
4
|
+
// and the explainer draws "Prüfen", checks the answer, gives the feedback with the message of a typical mistake, the
|
|
5
|
+
// task number and "Neue Aufgabe". Once the answer is checked, the field shows it as it is until the learner changes it.
|
|
6
|
+
import { computed, ref } from "vue";
|
|
7
|
+
import { fill, generate } from "./ProzentFeld.ts";
|
|
8
|
+
|
|
9
|
+
const props = defineProps<{
|
|
10
|
+
/** The task, with {G} for the number of squares and {p} for the percentage. */
|
|
11
|
+
task: string;
|
|
12
|
+
/** The count below the field, with {n} for the squares coloured and {G}. */
|
|
13
|
+
counter: string;
|
|
14
|
+
/** The name of a square for screen readers, with {n} for its number. */
|
|
15
|
+
cell: string;
|
|
16
|
+
/** The app's message for each typical mistake, in the order of about.mistakes, with {G}, {p} and {n}. */
|
|
17
|
+
mistakes: string[];
|
|
18
|
+
/** The task number, which the explainer gives. */
|
|
19
|
+
seed: number;
|
|
20
|
+
/** Whether the explainer checked the answer the field gives now. */
|
|
21
|
+
checked: boolean;
|
|
22
|
+
}>();
|
|
23
|
+
const emit = defineEmits<{ answer: [number] }>();
|
|
24
|
+
|
|
25
|
+
// the task of the number the explainer gives; "Neue Aufgabe" mounts the component afresh with another
|
|
26
|
+
const current = computed(() => generate(props.seed, props));
|
|
27
|
+
const coloured = ref<boolean[]>(Array.from({ length: current.value.G }, () => false));
|
|
28
|
+
const count = computed(() => coloured.value.filter(Boolean).length);
|
|
29
|
+
// ten squares to a row, five for a field of 25
|
|
30
|
+
const columns = computed(() => (current.value.G === 25 ? 5 : 10));
|
|
31
|
+
|
|
32
|
+
function toggle(index: number): void {
|
|
33
|
+
coloured.value[index] = !coloured.value[index];
|
|
34
|
+
emit("answer", count.value);
|
|
35
|
+
}
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<template>
|
|
39
|
+
<div class="prozent-feld">
|
|
40
|
+
<p>{{ fill(task, current) }}</p>
|
|
41
|
+
<div
|
|
42
|
+
class="prozent-feld-grid"
|
|
43
|
+
:class="{ 'prozent-feld-checked': checked }"
|
|
44
|
+
:style="{ gridTemplateColumns: `repeat(${columns}, 1fr)` }"
|
|
45
|
+
>
|
|
46
|
+
<button
|
|
47
|
+
v-for="(on, index) in coloured"
|
|
48
|
+
:key="index"
|
|
49
|
+
type="button"
|
|
50
|
+
:aria-pressed="on"
|
|
51
|
+
:aria-label="fill(cell, current, index + 1)"
|
|
52
|
+
@click="toggle(index)"
|
|
53
|
+
></button>
|
|
54
|
+
</div>
|
|
55
|
+
<p aria-live="polite">{{ fill(counter, current, count) }}</p>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
|
|
59
|
+
<style scoped>
|
|
60
|
+
.prozent-feld-grid {
|
|
61
|
+
display: grid;
|
|
62
|
+
gap: 2px;
|
|
63
|
+
max-width: 20rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.prozent-feld-grid button {
|
|
67
|
+
aspect-ratio: 1;
|
|
68
|
+
min-width: 1.5rem;
|
|
69
|
+
min-height: 1.5rem;
|
|
70
|
+
padding: 0;
|
|
71
|
+
border: 1px solid #1a1a1a;
|
|
72
|
+
border-radius: 0;
|
|
73
|
+
background: #fff;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.prozent-feld-grid button[aria-pressed="true"] {
|
|
77
|
+
background: #2f5fb3;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* the answer checked: its squares a little lighter until the learner changes it */
|
|
81
|
+
.prozent-feld-checked button[aria-pressed="true"] {
|
|
82
|
+
background: #5b7fc4;
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="300" viewBox="0 0 240 300">
|
|
2
|
+
<title>Hunderterfeld mit zwei Klammern</title>
|
|
3
|
+
<rect x="20" y="46" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
4
|
+
<rect x="40" y="46" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
5
|
+
<rect x="60" y="46" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
6
|
+
<rect x="80" y="46" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
7
|
+
<rect x="100" y="46" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
8
|
+
<rect x="120" y="46" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
9
|
+
<rect x="140" y="46" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
10
|
+
<rect x="160" y="46" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
11
|
+
<rect x="180" y="46" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
12
|
+
<rect x="200" y="46" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
13
|
+
<rect x="20" y="66" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
14
|
+
<rect x="40" y="66" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
15
|
+
<rect x="60" y="66" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
16
|
+
<rect x="80" y="66" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
17
|
+
<rect x="100" y="66" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
18
|
+
<rect x="120" y="66" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
19
|
+
<rect x="140" y="66" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
20
|
+
<rect x="160" y="66" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
21
|
+
<rect x="180" y="66" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
22
|
+
<rect x="200" y="66" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
23
|
+
<rect x="20" y="86" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
24
|
+
<rect x="40" y="86" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
25
|
+
<rect x="60" y="86" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
26
|
+
<rect x="80" y="86" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
27
|
+
<rect x="100" y="86" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
28
|
+
<rect x="120" y="86" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
29
|
+
<rect x="140" y="86" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
30
|
+
<rect x="160" y="86" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
31
|
+
<rect x="180" y="86" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
32
|
+
<rect x="200" y="86" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
33
|
+
<rect x="20" y="106" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
34
|
+
<rect x="40" y="106" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
35
|
+
<rect x="60" y="106" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
36
|
+
<rect x="80" y="106" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
37
|
+
<rect x="100" y="106" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
38
|
+
<rect x="120" y="106" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
39
|
+
<rect x="140" y="106" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
40
|
+
<rect x="160" y="106" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
41
|
+
<rect x="180" y="106" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
42
|
+
<rect x="200" y="106" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
43
|
+
<rect x="20" y="126" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
44
|
+
<rect x="40" y="126" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
45
|
+
<rect x="60" y="126" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
46
|
+
<rect x="80" y="126" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
47
|
+
<rect x="100" y="126" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
48
|
+
<rect x="120" y="126" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
49
|
+
<rect x="140" y="126" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
50
|
+
<rect x="160" y="126" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
51
|
+
<rect x="180" y="126" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
52
|
+
<rect x="200" y="126" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
53
|
+
<rect x="20" y="146" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
54
|
+
<rect x="40" y="146" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
55
|
+
<rect x="60" y="146" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
56
|
+
<rect x="80" y="146" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
57
|
+
<rect x="100" y="146" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
58
|
+
<rect x="120" y="146" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
59
|
+
<rect x="140" y="146" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
60
|
+
<rect x="160" y="146" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
61
|
+
<rect x="180" y="146" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
62
|
+
<rect x="200" y="146" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
63
|
+
<rect x="20" y="166" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
64
|
+
<rect x="40" y="166" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
65
|
+
<rect x="60" y="166" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
66
|
+
<rect x="80" y="166" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
67
|
+
<rect x="100" y="166" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
68
|
+
<rect x="120" y="166" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
69
|
+
<rect x="140" y="166" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
70
|
+
<rect x="160" y="166" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
71
|
+
<rect x="180" y="166" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
72
|
+
<rect x="200" y="166" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
73
|
+
<rect x="20" y="186" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
74
|
+
<rect x="40" y="186" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
75
|
+
<rect x="60" y="186" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
76
|
+
<rect x="80" y="186" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
77
|
+
<rect x="100" y="186" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
78
|
+
<rect x="120" y="186" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
79
|
+
<rect x="140" y="186" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
80
|
+
<rect x="160" y="186" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
81
|
+
<rect x="180" y="186" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
82
|
+
<rect x="200" y="186" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
83
|
+
<rect x="20" y="206" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
84
|
+
<rect x="40" y="206" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
85
|
+
<rect x="60" y="206" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
86
|
+
<rect x="80" y="206" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
87
|
+
<rect x="100" y="206" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
88
|
+
<rect x="120" y="206" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
89
|
+
<rect x="140" y="206" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
90
|
+
<rect x="160" y="206" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
91
|
+
<rect x="180" y="206" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
92
|
+
<rect x="200" y="206" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
93
|
+
<rect x="20" y="226" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
94
|
+
<rect x="40" y="226" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
95
|
+
<rect x="60" y="226" width="20" height="20" fill="#4a90d9" stroke="#6b6b6b" stroke-width="1"/>
|
|
96
|
+
<rect x="80" y="226" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
97
|
+
<rect x="100" y="226" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
98
|
+
<rect x="120" y="226" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
99
|
+
<rect x="140" y="226" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
100
|
+
<rect x="160" y="226" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
101
|
+
<rect x="180" y="226" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
102
|
+
<rect x="200" y="226" width="20" height="20" fill="#ffffff" stroke="#6b6b6b" stroke-width="1"/>
|
|
103
|
+
<path d="M20 40 Q20 35 25 35 H45 Q50 35 50 28 Q50 35 55 35 H75 Q80 35 80 40" fill="none" stroke="#1a1a1a" stroke-width="2"/>
|
|
104
|
+
<path d="M20 252 Q20 257 25 257 H115 Q120 257 120 264 Q120 257 125 257 H215 Q220 257 220 252" fill="none" stroke="#1a1a1a" stroke-width="2"/>
|
|
105
|
+
</svg>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# yaml-language-server: $schema=../../node_modules/@lernapps/app-templates/runtime/explainer/explainer.v1.schema.json
|
|
2
|
+
title: Prozent
|
|
3
|
+
summary: Mit Prozenten vergleichst du Anteile, egal wie groß das Ganze ist.
|
|
4
|
+
pages: [prozentwert, prozentsatz, grundwert]
|
|
5
|
+
# The chapter's self-assessment, offered on the start page (an app with one chapter): three or four tasks per page,
|
|
6
|
+
# prozentwert-ueben and the exercise component prozentfeld each drawing a task of their own, the open task
|
|
7
|
+
# tauschen-erklaeren answered in the learner's own words.
|
|
8
|
+
selfAssessment:
|
|
9
|
+
pages:
|
|
10
|
+
- exercises:
|
|
11
|
+
- /prozent/prozentwert/#prozentwert-ueben
|
|
12
|
+
- /prozent/prozentwert/#prozentfeld
|
|
13
|
+
- /prozent/prozentwert/#tauschen-erklaeren
|
|
14
|
+
- /prozent/prozentsatz/#welche-rechnung
|
|
15
|
+
- exercises:
|
|
16
|
+
- /prozent/prozentsatz/#prozentsatz-ueben
|
|
17
|
+
- /prozent/grundwert/#klammern
|
|
18
|
+
- /prozent/grundwert/#grundwert-ueben
|