test: gebruik eigen oefenbiljetten zonder markering
All checks were successful
dev - build & deploy naar test / build-and-deploy (push) Successful in 38s

This commit is contained in:
Ramon 2026-07-15 22:32:20 +02:00
parent 2742196c11
commit ff91ae0f2b
13 changed files with 222 additions and 6 deletions

View file

@ -1 +1 @@
0.3.52-beta
0.3.53-beta

View file

@ -3,6 +3,6 @@
Deze afbeeldingen worden lokaal meegeleverd, zodat de geldwidget ook zonder internetverbinding werkt.
- **Munten (1, 2, 5, 10, 20 en 50 cent, €1 en €2):** actuele gemeenschappelijke zijden van de Europese Commissie, gedownload van [Common sides of euro coins](https://economy-finance.ec.europa.eu/euro/euro-coins-and-notes/euro-coins/common-sides-euro-coins_en) op 15 juli 2026. De tweedimensionale afbeeldingen zijn eigendom van de Europese Unie en worden hier educatief gebruikt volgens de reproductievoorwaarden van de Europese Commissie.
- **Bankbiljetten (€5, €10, €20 en €50):** voorzijde van de Europa-serie met Lagarde-handtekening uit het officiële [ECB-pakket met 72-dpi SPECIMEN-afbeeldingen](https://www.ecb.europa.eu/euro/shared/img/euro_banknotes_specimen_72dpi.zip), gedownload op 15 juli 2026. De zichtbare SPECIMEN-markering en originele 72-dpi-bestanden worden behouden volgens de [ECB-reproductieregels](https://www.ecb.europa.eu/euro/banknotes/images/html/index.en.html).
- **Oefenbiljetten (€5, €10, €20 en €50):** eigen vectorontwerpen voor Teach. Alleen de herkenbare waardekleuren en onderlinge verhoudingen volgen de [ECB-uitleg over eurobiljetten](https://www.ecb.europa.eu/euro/visually/html/index.en.html). De illustraties, patronen, serienummers en opschriften zijn nieuw ontworpen en stellen geen officiële eurobiljetten voor.
De bestandsnamen gebruiken centen als waarde, bijvoorbeeld coin-200.png voor €2 en note-500.jpg voor €5.
De bestandsnamen gebruiken centen als waarde, bijvoorbeeld coin-200.png voor €2 en note-500.svg voor €5.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 556 KiB

View file

@ -0,0 +1,52 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1270 670" width="1270" height="670">
<defs>
<linearGradient id="bgn10" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#f4c6bc"/><stop offset=".48" stop-color="#ce7775"/><stop offset="1" stop-color="#8f3f4a"/></linearGradient>
<radialGradient id="sealn10"><stop stop-color="#fff" stop-opacity=".72"/><stop offset=".55" stop-color="#f4c6bc" stop-opacity=".54"/><stop offset="1" stop-color="#8f3f4a" stop-opacity=".34"/></radialGradient>
<linearGradient id="foiln10" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#fff" stop-opacity=".9"/><stop offset=".3" stop-color="#c9dce4"/><stop offset=".65" stop-color="#f8df8b"/><stop offset="1" stop-color="#8dc7d4"/></linearGradient>
<pattern id="waven10" width="120" height="54" patternUnits="userSpaceOnUse"><path d="M-10 27 Q20 2 50 27t60 0t60 0" fill="none" stroke="#fff" stroke-opacity=".19" stroke-width="5"/><path d="M-10 37 Q20 12 50 37t60 0t60 0" fill="none" stroke="#8f3f4a" stroke-opacity=".13" stroke-width="3"/></pattern>
<pattern id="mathn10" width="132" height="92" patternUnits="userSpaceOnUse"><text x="8" y="33" font-family="Arial,sans-serif" font-size="27" font-weight="700" fill="#fff" opacity=".16">+ ×</text><text x="50" y="76" font-family="Arial,sans-serif" font-size="25" font-weight="700" fill="#8f3f4a" opacity=".13"> ÷</text></pattern>
<clipPath id="clipn10"><rect width="1270" height="670" rx="34"/></clipPath>
</defs>
<g clip-path="url(#clipn10)">
<rect width="1270" height="670" fill="url(#bgn10)"/>
<rect width="1270" height="670" fill="url(#waven10)"/>
<rect x="394" width="597" height="670" fill="url(#mathn10)"/>
<path d="M0 482 C 279 348 495 637 737 469 S 1092 335 1270 489 L 1270 670 L0 670Z" fill="#fff" opacity=".13"/>
<circle cx="216" cy="355" r="188" fill="url(#sealn10)" stroke="#fff" stroke-opacity=".55" stroke-width="8"/>
<circle cx="216" cy="355" r="147" fill="none" stroke="#8f3f4a" stroke-opacity=".36" stroke-width="7" stroke-dasharray="13 9"/>
<rect x="927" y="-15" width="74" height="700" rx="18" fill="url(#foiln10)" opacity=".82"/>
<rect x="952" y="0" width="7" height="670" fill="#fff" opacity=".56"/>
</g>
<rect x="13" y="13" width="1244" height="644" rx="29" fill="none" stroke="#fff" stroke-opacity=".8" stroke-width="9"/>
<rect x="28" y="28" width="1214" height="614" rx="22" fill="none" stroke="#8f3f4a" stroke-opacity=".38" stroke-width="4" stroke-dasharray="20 9"/>
<g font-family="Arial,sans-serif">
<text x="58" y="77" font-size="35" font-weight="900" letter-spacing="8" fill="#58242d">OEFENGELD</text>
<text x="1212" y="75" text-anchor="end" font-size="21" font-weight="700" letter-spacing="4" fill="#58242d" opacity=".8">TEACH 2026 · B10</text>
<text x="216" y="405" text-anchor="middle" font-size="248" font-weight="900" fill="#58242d">10</text>
<text x="216" y="482" text-anchor="middle" font-size="34" font-weight="900" letter-spacing="7" fill="#58242d">EURO</text>
<text x="1212" y="395" text-anchor="end" font-size="161" font-weight="900" fill="#58242d" opacity=".88">€10</text>
<text x="58" y="627" font-size="25" font-weight="900" letter-spacing="5" fill="#58242d">GEEN BETAALMIDDEL</text>
<text x="1212" y="627" text-anchor="end" font-size="20" font-weight="700" letter-spacing="3" fill="#58242d" opacity=".76">LEREN · TELLEN · REKENEN</text>
</g>
<g transform="translate(457 147)" fill="none" stroke="#58242d" stroke-opacity=".55">
<rect x="0" y="43" width="394" height="275" rx="25" fill="#fff" fill-opacity=".2" stroke-width="7"/>
<path d="M32 290 V170 Q32 83 95 83 Q158 83 158 170 V290" stroke-width="9"/>
<path d="M185 290 V148 Q185 58 252 58 Q319 58 319 148 V290" stroke-width="9"/>
<path d="M8 43 L197 0 L386 43" stroke-width="10" stroke-linecap="round"/>
</g>
<g fill="#fff" opacity=".72">
<circle cx="1003" cy="456" r="8"/>
<circle cx="1052" cy="456" r="8"/>
<circle cx="1100" cy="456" r="8"/>
<circle cx="1148" cy="456" r="8"/>
<circle cx="1003" cy="499" r="8"/>
<circle cx="1052" cy="499" r="8"/>
<circle cx="1100" cy="499" r="8"/>
<circle cx="1148" cy="499" r="8"/>
<circle cx="1003" cy="543" r="8"/>
<circle cx="1052" cy="543" r="8"/>
<circle cx="1100" cy="543" r="8"/>
<circle cx="1148" cy="543" r="8"/>
</g>
<g transform="translate(964 194)" fill="#58242d" opacity=".75"><circle r="37"/><text x="0" y="17" text-anchor="middle" font-family="Arial,sans-serif" font-size="50" font-weight="900" fill="#fff"></text></g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 526 KiB

View file

@ -0,0 +1,52 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1330 720" width="1330" height="720">
<defs>
<linearGradient id="bgn20" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#bfe4ef"/><stop offset=".48" stop-color="#559bc1"/><stop offset="1" stop-color="#245f87"/></linearGradient>
<radialGradient id="sealn20"><stop stop-color="#fff" stop-opacity=".72"/><stop offset=".55" stop-color="#bfe4ef" stop-opacity=".54"/><stop offset="1" stop-color="#245f87" stop-opacity=".34"/></radialGradient>
<linearGradient id="foiln20" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#fff" stop-opacity=".9"/><stop offset=".3" stop-color="#d6bfdc"/><stop offset=".65" stop-color="#f8df8b"/><stop offset="1" stop-color="#8dc7d4"/></linearGradient>
<pattern id="waven20" width="120" height="54" patternUnits="userSpaceOnUse"><path d="M-10 27 Q20 2 50 27t60 0t60 0" fill="none" stroke="#fff" stroke-opacity=".19" stroke-width="5"/><path d="M-10 37 Q20 12 50 37t60 0t60 0" fill="none" stroke="#245f87" stroke-opacity=".13" stroke-width="3"/></pattern>
<pattern id="mathn20" width="132" height="92" patternUnits="userSpaceOnUse"><text x="8" y="33" font-family="Arial,sans-serif" font-size="27" font-weight="700" fill="#fff" opacity=".16">+ ×</text><text x="50" y="76" font-family="Arial,sans-serif" font-size="25" font-weight="700" fill="#245f87" opacity=".13"> ÷</text></pattern>
<clipPath id="clipn20"><rect width="1330" height="720" rx="34"/></clipPath>
</defs>
<g clip-path="url(#clipn20)">
<rect width="1330" height="720" fill="url(#bgn20)"/>
<rect width="1330" height="720" fill="url(#waven20)"/>
<rect x="412" width="625" height="720" fill="url(#mathn20)"/>
<path d="M0 518 C 293 374 519 684 771 504 S 1144 360 1330 526 L 1330 720 L0 720Z" fill="#fff" opacity=".13"/>
<circle cx="226" cy="382" r="202" fill="url(#sealn20)" stroke="#fff" stroke-opacity=".55" stroke-width="8"/>
<circle cx="226" cy="382" r="158" fill="none" stroke="#245f87" stroke-opacity=".36" stroke-width="7" stroke-dasharray="13 9"/>
<rect x="971" y="-15" width="77" height="750" rx="18" fill="url(#foiln20)" opacity=".82"/>
<rect x="998" y="0" width="7" height="720" fill="#fff" opacity=".56"/>
</g>
<rect x="13" y="13" width="1304" height="694" rx="29" fill="none" stroke="#fff" stroke-opacity=".8" stroke-width="9"/>
<rect x="28" y="28" width="1274" height="664" rx="22" fill="none" stroke="#245f87" stroke-opacity=".38" stroke-width="4" stroke-dasharray="20 9"/>
<g font-family="Arial,sans-serif">
<text x="58" y="77" font-size="37" font-weight="900" letter-spacing="8" fill="#153f62">OEFENGELD</text>
<text x="1272" y="75" text-anchor="end" font-size="22" font-weight="700" letter-spacing="4" fill="#153f62" opacity=".8">TEACH 2026 · C20</text>
<text x="226" y="436" text-anchor="middle" font-size="266" font-weight="900" fill="#153f62">20</text>
<text x="226" y="519" text-anchor="middle" font-size="36" font-weight="900" letter-spacing="7" fill="#153f62">EURO</text>
<text x="1272" y="425" text-anchor="end" font-size="173" font-weight="900" fill="#153f62" opacity=".88">€20</text>
<text x="58" y="677" font-size="27" font-weight="900" letter-spacing="5" fill="#153f62">GEEN BETAALMIDDEL</text>
<text x="1272" y="677" text-anchor="end" font-size="22" font-weight="700" letter-spacing="3" fill="#153f62" opacity=".76">LEREN · TELLEN · REKENEN</text>
</g>
<g transform="translate(479 158)" fill="none" stroke="#153f62" stroke-opacity=".55">
<rect x="0" y="47" width="412" height="296" rx="25" fill="#fff" fill-opacity=".2" stroke-width="7"/>
<path d="M33 311 V183 Q33 89 99 89 Q165 89 165 183 V311" stroke-width="9"/>
<path d="M194 311 V159 Q194 62 264 62 Q334 62 334 159 V311" stroke-width="9"/>
<path d="M8 47 L206 0 L404 47" stroke-width="10" stroke-linecap="round"/>
</g>
<g fill="#fff" opacity=".72">
<circle cx="1051" cy="490" r="9"/>
<circle cx="1101" cy="490" r="9"/>
<circle cx="1152" cy="490" r="9"/>
<circle cx="1202" cy="490" r="9"/>
<circle cx="1051" cy="536" r="9"/>
<circle cx="1101" cy="536" r="9"/>
<circle cx="1152" cy="536" r="9"/>
<circle cx="1202" cy="536" r="9"/>
<circle cx="1051" cy="583" r="9"/>
<circle cx="1101" cy="583" r="9"/>
<circle cx="1152" cy="583" r="9"/>
<circle cx="1202" cy="583" r="9"/>
</g>
<g transform="translate(1010 209)" fill="#153f62" opacity=".75"><circle r="40"/><text x="0" y="19" text-anchor="middle" font-family="Arial,sans-serif" font-size="54" font-weight="900" fill="#fff"></text></g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 456 KiB

View file

@ -0,0 +1,52 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 620" width="1200" height="620">
<defs>
<linearGradient id="bgn5" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#e8eceb"/><stop offset=".48" stop-color="#a9b2b3"/><stop offset="1" stop-color="#657277"/></linearGradient>
<radialGradient id="sealn5"><stop stop-color="#fff" stop-opacity=".72"/><stop offset=".55" stop-color="#e8eceb" stop-opacity=".54"/><stop offset="1" stop-color="#657277" stop-opacity=".34"/></radialGradient>
<linearGradient id="foiln5" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#fff" stop-opacity=".9"/><stop offset=".3" stop-color="#b9d6d9"/><stop offset=".65" stop-color="#f8df8b"/><stop offset="1" stop-color="#8dc7d4"/></linearGradient>
<pattern id="waven5" width="120" height="54" patternUnits="userSpaceOnUse"><path d="M-10 27 Q20 2 50 27t60 0t60 0" fill="none" stroke="#fff" stroke-opacity=".19" stroke-width="5"/><path d="M-10 37 Q20 12 50 37t60 0t60 0" fill="none" stroke="#657277" stroke-opacity=".13" stroke-width="3"/></pattern>
<pattern id="mathn5" width="132" height="92" patternUnits="userSpaceOnUse"><text x="8" y="33" font-family="Arial,sans-serif" font-size="27" font-weight="700" fill="#fff" opacity=".16">+ ×</text><text x="50" y="76" font-family="Arial,sans-serif" font-size="25" font-weight="700" fill="#657277" opacity=".13"> ÷</text></pattern>
<clipPath id="clipn5"><rect width="1200" height="620" rx="34"/></clipPath>
</defs>
<g clip-path="url(#clipn5)">
<rect width="1200" height="620" fill="url(#bgn5)"/>
<rect width="1200" height="620" fill="url(#waven5)"/>
<rect x="372" width="564" height="620" fill="url(#mathn5)"/>
<path d="M0 446 C 264 322 468 589 696 434 S 1032 310 1200 453 L 1200 620 L0 620Z" fill="#fff" opacity=".13"/>
<circle cx="204" cy="329" r="174" fill="url(#sealn5)" stroke="#fff" stroke-opacity=".55" stroke-width="8"/>
<circle cx="204" cy="329" r="136" fill="none" stroke="#657277" stroke-opacity=".36" stroke-width="7" stroke-dasharray="13 9"/>
<rect x="876" y="-15" width="70" height="650" rx="18" fill="url(#foiln5)" opacity=".82"/>
<rect x="900" y="0" width="7" height="620" fill="#fff" opacity=".56"/>
</g>
<rect x="13" y="13" width="1174" height="594" rx="29" fill="none" stroke="#fff" stroke-opacity=".8" stroke-width="9"/>
<rect x="28" y="28" width="1144" height="564" rx="22" fill="none" stroke="#657277" stroke-opacity=".38" stroke-width="4" stroke-dasharray="20 9"/>
<g font-family="Arial,sans-serif">
<text x="58" y="77" font-size="32" font-weight="900" letter-spacing="8" fill="#273a40">OEFENGELD</text>
<text x="1142" y="75" text-anchor="end" font-size="19" font-weight="700" letter-spacing="4" fill="#273a40" opacity=".8">TEACH 2026 · A05</text>
<text x="204" y="376" text-anchor="middle" font-size="229" font-weight="900" fill="#273a40">5</text>
<text x="204" y="447" text-anchor="middle" font-size="31" font-weight="900" letter-spacing="7" fill="#273a40">EURO</text>
<text x="1142" y="366" text-anchor="end" font-size="149" font-weight="900" fill="#273a40" opacity=".88">€5</text>
<text x="58" y="577" font-size="23" font-weight="900" letter-spacing="5" fill="#273a40">GEEN BETAALMIDDEL</text>
<text x="1142" y="577" text-anchor="end" font-size="19" font-weight="700" letter-spacing="3" fill="#273a40" opacity=".76">LEREN · TELLEN · REKENEN</text>
</g>
<g transform="translate(432 136)" fill="none" stroke="#273a40" stroke-opacity=".55">
<rect x="0" y="40" width="372" height="255" rx="25" fill="#fff" fill-opacity=".2" stroke-width="7"/>
<path d="M30 268 V157 Q30 77 89 77 Q149 77 149 157 V268" stroke-width="9"/>
<path d="M175 268 V137 Q175 54 238 54 Q301 54 301 137 V268" stroke-width="9"/>
<path d="M7 40 L186 0 L365 40" stroke-width="10" stroke-linecap="round"/>
</g>
<g fill="#fff" opacity=".72">
<circle cx="948" cy="422" r="7"/>
<circle cx="994" cy="422" r="7"/>
<circle cx="1039" cy="422" r="7"/>
<circle cx="1085" cy="422" r="7"/>
<circle cx="948" cy="462" r="7"/>
<circle cx="994" cy="462" r="7"/>
<circle cx="1039" cy="462" r="7"/>
<circle cx="1085" cy="462" r="7"/>
<circle cx="948" cy="502" r="7"/>
<circle cx="994" cy="502" r="7"/>
<circle cx="1039" cy="502" r="7"/>
<circle cx="1085" cy="502" r="7"/>
</g>
<g transform="translate(911 180)" fill="#273a40" opacity=".75"><circle r="34"/><text x="0" y="16" text-anchor="middle" font-family="Arial,sans-serif" font-size="47" font-weight="900" fill="#fff"></text></g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 KiB

View file

@ -0,0 +1,52 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 770" width="1400" height="770">
<defs>
<linearGradient id="bgn50" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#f8d39b"/><stop offset=".48" stop-color="#e49448"/><stop offset="1" stop-color="#a95726"/></linearGradient>
<radialGradient id="sealn50"><stop stop-color="#fff" stop-opacity=".72"/><stop offset=".55" stop-color="#f8d39b" stop-opacity=".54"/><stop offset="1" stop-color="#a95726" stop-opacity=".34"/></radialGradient>
<linearGradient id="foiln50" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#fff" stop-opacity=".9"/><stop offset=".3" stop-color="#bdd8ce"/><stop offset=".65" stop-color="#f8df8b"/><stop offset="1" stop-color="#8dc7d4"/></linearGradient>
<pattern id="waven50" width="120" height="54" patternUnits="userSpaceOnUse"><path d="M-10 27 Q20 2 50 27t60 0t60 0" fill="none" stroke="#fff" stroke-opacity=".19" stroke-width="5"/><path d="M-10 37 Q20 12 50 37t60 0t60 0" fill="none" stroke="#a95726" stroke-opacity=".13" stroke-width="3"/></pattern>
<pattern id="mathn50" width="132" height="92" patternUnits="userSpaceOnUse"><text x="8" y="33" font-family="Arial,sans-serif" font-size="27" font-weight="700" fill="#fff" opacity=".16">+ ×</text><text x="50" y="76" font-family="Arial,sans-serif" font-size="25" font-weight="700" fill="#a95726" opacity=".13"> ÷</text></pattern>
<clipPath id="clipn50"><rect width="1400" height="770" rx="34"/></clipPath>
</defs>
<g clip-path="url(#clipn50)">
<rect width="1400" height="770" fill="url(#bgn50)"/>
<rect width="1400" height="770" fill="url(#waven50)"/>
<rect x="434" width="658" height="770" fill="url(#mathn50)"/>
<path d="M0 554 C 308 400 546 732 812 539 S 1204 385 1400 562 L 1400 770 L0 770Z" fill="#fff" opacity=".13"/>
<circle cx="238" cy="408" r="216" fill="url(#sealn50)" stroke="#fff" stroke-opacity=".55" stroke-width="8"/>
<circle cx="238" cy="408" r="168" fill="none" stroke="#a95726" stroke-opacity=".36" stroke-width="7" stroke-dasharray="13 9"/>
<rect x="1022" y="-15" width="81" height="800" rx="18" fill="url(#foiln50)" opacity=".82"/>
<rect x="1050" y="0" width="7" height="770" fill="#fff" opacity=".56"/>
</g>
<rect x="13" y="13" width="1374" height="744" rx="29" fill="none" stroke="#fff" stroke-opacity=".8" stroke-width="9"/>
<rect x="28" y="28" width="1344" height="714" rx="22" fill="none" stroke="#a95726" stroke-opacity=".38" stroke-width="4" stroke-dasharray="20 9"/>
<g font-family="Arial,sans-serif">
<text x="58" y="77" font-size="40" font-weight="900" letter-spacing="8" fill="#6b321a">OEFENGELD</text>
<text x="1342" y="75" text-anchor="end" font-size="24" font-weight="700" letter-spacing="4" fill="#6b321a" opacity=".8">TEACH 2026 · D50</text>
<text x="238" y="466" text-anchor="middle" font-size="285" font-weight="900" fill="#6b321a">50</text>
<text x="238" y="554" text-anchor="middle" font-size="39" font-weight="900" letter-spacing="7" fill="#6b321a">EURO</text>
<text x="1342" y="454" text-anchor="end" font-size="185" font-weight="900" fill="#6b321a" opacity=".88">€50</text>
<text x="58" y="727" font-size="28" font-weight="900" letter-spacing="5" fill="#6b321a">GEEN BETAALMIDDEL</text>
<text x="1342" y="727" text-anchor="end" font-size="23" font-weight="700" letter-spacing="3" fill="#6b321a" opacity=".76">LEREN · TELLEN · REKENEN</text>
</g>
<g transform="translate(504 169)" fill="none" stroke="#6b321a" stroke-opacity=".55">
<rect x="0" y="50" width="434" height="316" rx="25" fill="#fff" fill-opacity=".2" stroke-width="7"/>
<path d="M35 333 V196 Q35 96 104 96 Q174 96 174 196 V333" stroke-width="9"/>
<path d="M204 333 V171 Q204 67 278 67 Q352 67 352 171 V333" stroke-width="9"/>
<path d="M9 50 L217 0 L425 50" stroke-width="10" stroke-linecap="round"/>
</g>
<g fill="#fff" opacity=".72">
<circle cx="1106" cy="524" r="9"/>
<circle cx="1159" cy="524" r="9"/>
<circle cx="1212" cy="524" r="9"/>
<circle cx="1266" cy="524" r="9"/>
<circle cx="1106" cy="574" r="9"/>
<circle cx="1159" cy="574" r="9"/>
<circle cx="1212" cy="574" r="9"/>
<circle cx="1266" cy="574" r="9"/>
<circle cx="1106" cy="624" r="9"/>
<circle cx="1159" cy="624" r="9"/>
<circle cx="1212" cy="624" r="9"/>
<circle cx="1266" cy="624" r="9"/>
</g>
<g transform="translate(1063 223)" fill="#6b321a" opacity=".75"><circle r="42"/><text x="0" y="20" text-anchor="middle" font-family="Arial,sans-serif" font-size="58" font-weight="900" fill="#fff"></text></g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -2,7 +2,7 @@
"use strict";
/* version shown until /api/version resolves (or if the fetch fails, e.g. offline).
Kept in sync by hand with the VERSION file at the repo root on every release. */
const VERSION = "0.3.52-beta";
const VERSION = "0.3.53-beta";
(function(){
const tag = document.getElementById("verTag");
tag.textContent = "v"+VERSION;

View file

@ -62,7 +62,7 @@ function mountMoney(root,init){
const paymentFor=price=>{const options=S.level===1?[500,1000]:S.level===2?[500,1000,2000]:[100,200,500,1000,2000,5000];return options.find(value=>value>price)||Math.ceil((price+1)/5000)*5000};
const breakdown=amount=>{const result=[];let rest=amount;denominations().forEach(value=>{while(rest>=value&&result.length<24){result.push(value);rest-=value}});return result.sort(()=>Math.random()-.5)};
const fixedIndices=()=>S.level===1?[0,2,3]:S.level===2?[0]:[],emptyDigits=()=>S.level===1?[0,null,0,0]:S.level===2?[0,null,null,null]:[null,null,null,null];
const piece=(value,interactive=false)=>{const el=document.createElement(interactive?'button':'span');if(interactive)el.type='button';const type=value>=500?'note':'coin',extension=value>=500?'jpg':'png';el.className='money-piece '+type;el.dataset.value=value;const image=document.createElement('img'),fallback=document.createElement('span');image.className='money-piece-image';image.src=`/img/money/${type}-${value}.${extension}`;image.alt='';image.draggable=false;image.decoding='async';image.setAttribute('aria-hidden','true');image.onerror=()=>el.classList.add('image-missing');fallback.className='money-piece-fallback';fallback.textContent=value>=100?'€'+value/100:value+'c';el.append(image,fallback);el.setAttribute('aria-label',format(value));return el};
const piece=(value,interactive=false)=>{const el=document.createElement(interactive?'button':'span');if(interactive)el.type='button';const type=value>=500?'note':'coin',extension=value>=500?'svg':'png';el.className='money-piece '+type;el.dataset.value=value;const image=document.createElement('img'),fallback=document.createElement('span');image.className='money-piece-image';image.src=`/img/money/${type}-${value}.${extension}`;image.alt='';image.draggable=false;image.decoding='async';image.setAttribute('aria-hidden','true');image.onerror=()=>el.classList.add('image-missing');fallback.className='money-piece-fallback';fallback.textContent=value>=100?'€'+value/100:value+'c';el.append(image,fallback);el.setAttribute('aria-label',format(value));return el};
const pile=(values,interactive=false,wallet=null)=>{const wrap=document.createElement('div');wrap.className='money-pile'+(interactive?' interactive':' readonly');values.forEach((value,index)=>{const el=piece(value,interactive);if(interactive){el.title=T('moneyRemove');el.onpointerdown=e=>{if(S.solved||(e.pointerType==='mouse'&&e.button!==0))return;e.preventDefault();const startX=e.clientX,startY=e.clientY,clone=el.cloneNode(true);clone.id='dragClone';clone.classList.add('money-drag-clone','from-wallet');document.body.append(clone);const moveTo=ev=>{const zoom=VZ();clone.style.left=ev.clientX/zoom+'px';clone.style.top=ev.clientY/zoom+'px'},over=ev=>{const r=wallet.getBoundingClientRect();return ev.clientX>=r.left&&ev.clientX<=r.right&&ev.clientY>=r.top&&ev.clientY<=r.bottom},hasMoved=ev=>Math.hypot(ev.clientX-startX,ev.clientY-startY)>=6;moveTo(e);const move=ev=>{moveTo(ev);wallet.classList.toggle('money-remove-target',hasMoved(ev)&&!over(ev))},clean=()=>{document.removeEventListener('pointermove',move);document.removeEventListener('pointerup',up);document.removeEventListener('pointercancel',cancel);wallet.classList.remove('money-remove-target');clone.remove()},remove=()=>{S.selected.splice(index,1);S.feedback='';draw()},up=ev=>{const moved=hasMoved(ev),outside=!over(ev);clean();if(!moved||(moved&&outside))remove()},cancel=()=>clean();document.addEventListener('pointermove',move);document.addEventListener('pointerup',up);document.addEventListener('pointercancel',cancel)};el.onkeydown=e=>{if((e.key==='Enter'||e.key===' '||e.key==='Delete'||e.key==='Backspace')&&!S.solved){e.preventDefault();S.selected.splice(index,1);S.feedback='';draw()}}}wrap.append(el)});return wrap};
const amountDisplay=(cents,compact=false)=>{const wrap=document.createElement('div');wrap.className='money-assignment'+(compact?' compact':'');if(['amount','both'].includes(S.style)){const output=document.createElement('output');output.className='money-task-amount';output.textContent=format(cents);wrap.append(output)}if(['words','both'].includes(S.style)){const words=document.createElement('p');words.className='money-task-words';words.textContent=amountWords(cents);wrap.append(words)}return wrap};
const woodDigit=value=>{const block=document.createElement('span');block.className='blok sm money-digit-block';block.dataset.digit=value;const label=document.createElement('span');label.className='bl';label.textContent=String(value);const dots=dotGrid(Number(value));dots.classList.add('blok-dots');block.append(label,dots);return block};

View file

@ -131,9 +131,17 @@ test('geldrekenen biedt drie niveaus, leerwijzen, spellen en directe bediening',
assert.ok(moneySource.includes("/img/money/"));
assert.ok(moneySource.includes("image.draggable=false"));
assert.doesNotMatch(moneySource,/money-(?:arch|hologram|serial|stars|map|unit)/);
for(const file of ['coin-1.png','coin-2.png','coin-5.png','coin-10.png','coin-20.png','coin-50.png','coin-100.png','coin-200.png','note-500.jpg','note-1000.jpg','note-2000.jpg','note-5000.jpg']){
for(const file of ['coin-1.png','coin-2.png','coin-5.png','coin-10.png','coin-20.png','coin-50.png','coin-100.png','coin-200.png']){
const asset=await readFile('public/img/money/'+file);
assert.ok(asset.length>5000,file);
}
assert.ok(moneySource.includes("extension=value>=500?'svg':'png'"));
for(const file of ['note-500.svg','note-1000.svg','note-2000.svg','note-5000.svg']){
const asset=await readFile('public/img/money/'+file,'utf8');
assert.match(asset,/<svg[^>]+viewBox=/,file);
assert.match(asset,/>OEFENGELD<\/text>/,file);
assert.match(asset,/>GEEN BETAALMIDDEL<\/text>/,file);
assert.doesNotMatch(asset,/SPECIMEN/i,file);
}
assert.match(board,/id:"money"[^\n]*w:580, h:560, minW:380, minH:360/);
});