|
83 | 83 | - name: mstack-default |
84 | 84 | tag: mstack |
85 | 85 | match: "." |
86 | | - variables: |
87 | | - - Operator: "@data-operator" |
88 | | - - StackAlign: "@stackalign" |
89 | 86 | replace: |
90 | 87 | - bookmark: "@id" |
91 | 88 | - test: |
92 | | - - if: "$StackAlign='center'" |
| 89 | + - if: "@stackalign='center'" |
93 | 90 | then: [t: "centered"] |
94 | | - - else_if: "$StackAlign='left'" |
| 91 | + - else_if: "@stackalign='left'" |
95 | 92 | then: [t: "left-aligned"] |
96 | 93 | - test: |
97 | | - - if: "$Operator='+'" |
| 94 | + - if: "@data-operator='+'" |
98 | 95 | then: |
99 | 96 | - t: "addition problem" |
100 | | - - t: ";" |
101 | | - - else_if: "$Operator='-' or $Operator='−'" |
| 97 | + - pause: long |
| 98 | + - else_if: "@data-operator='-' or @data-operator='−'" |
102 | 99 | then: |
103 | 100 | - t: "subtraction problem" |
104 | | - - t: ";" |
105 | | - - else_if: "$Operator='×'" |
| 101 | + - pause: long |
| 102 | + - else_if: "@data-operator='×'" |
106 | 103 | then: |
107 | 104 | - t: "multiplication problem" |
108 | | - - t: ";" |
| 105 | + - pause: long |
109 | 106 | else: [t: "rows of numbers"] |
110 | 107 | - x: "*" |
111 | 108 | - pause: 500 |
112 | 109 | - bookmark: "@id" |
113 | 110 | - test: |
114 | | - if: "$Operator=' ' or not($Operator)" |
| 111 | + if: "@data-operator=' ' or not(@data-operator)" |
115 | 112 | then: [t: "end of numbers"] |
116 | 113 | else: [t: "end of problem"] |
117 | 114 | - pause: 200 |
|
175 | 172 |
|
176 | 173 | - name: elem-math-mn-decimal |
177 | 174 | tag: mn |
178 | | - match: "@data-decimalpoint and contains(., @data-decimalpoint) and string-length(.) - string-length(translate(., @data-decimalpoint, '')) = 1 and |
179 | | - (@data-decimalpoint != $DecimalSeparators or @data-decimalpoint = ',') and |
| 175 | + match: "$DecPt!='' and contains(., $DecPt) and string-length(.) - string-length(translate(., $DecPt, '')) = 1 and |
| 176 | + ($DecPt != $DecimalSeparators or $DecPt = ',') and |
180 | 177 | ((parent::*[self::m:mlongdiv] and count(preceding-sibling::*) < 3) or @data-elem-whole='true')" |
181 | 178 | variables: |
182 | | - - DecSep: "@data-decimalpoint" |
| 179 | + - DecPt: "IfThenElse(parent::m:msrow/@data-decimalpoint, parent::m:msrow/@data-decimalpoint, IfThenElse(parent::m:mscarries/@data-decimalpoint, parent::m:mscarries/@data-decimalpoint, IfThenElse(ancestor::m:mstack/@data-decimalpoint, ancestor::m:mstack/@data-decimalpoint, ancestor::m:mlongdiv/@data-decimalpoint)))" |
| 180 | + - DecSep: "$DecPt" |
183 | 181 | replace: |
184 | 182 | - bookmark: "@id" |
185 | 183 | - x: "concat(translate(translate(substring-before(., $DecSep), ',', ' '), '\u00A0\u202F', ' '), $DecimalSeparators, translate(translate(substring-after(., $DecSep), ',', ' '), '\u00A0\u202F', ' '))" |
|
201 | 199 | - name: elem-math-repeating-decimal-mn |
202 | 200 | tag: mn |
203 | 201 | match: "@data-repeating-decimal-digit='true'" |
| 202 | + variables: |
| 203 | + - DecPt: "IfThenElse(parent::m:msrow/@data-decimalpoint, parent::m:msrow/@data-decimalpoint, IfThenElse(ancestor::m:mstack/@data-decimalpoint, ancestor::m:mstack/@data-decimalpoint, '.'))" |
204 | 204 | replace: |
205 | 205 | - bookmark: "@id" |
206 | 206 | - test: |
207 | | - - if: ".='.' and @data-decimalpoint='.'" |
| 207 | + - if: ".='.' and $DecPt='.'" |
208 | 208 | then: [t: "point"] |
209 | | - - else_if: ".=',' and @data-decimalpoint=','" |
| 209 | + - else_if: ".=',' and $DecPt=','" |
210 | 210 | then: [t: "comma"] |
211 | 211 | - else_if: ".=' '" |
212 | 212 | then: [t: "space"] |
|
233 | 233 | - t: "in the" |
234 | 234 | - x: "DefinitionValue(string($Column), 'Speech', 'ElemMathPlace')" |
235 | 235 | - t: "column" |
| 236 | + # FIX: this looks like an AI-generated mess |
236 | 237 | - test: |
237 | 238 | - if: "following-sibling::*[self::m:mn] and ../following-sibling::*[1][self::m:mscarries]" |
238 | 239 | then: [pause: 200] |
|
334 | 335 |
|
335 | 336 | # --- msrow / msline (general) --- |
336 | 337 |
|
337 | | -- name: msrow-stack-trailing-operator |
338 | | - tag: msrow |
339 | | - match: |
340 | | - - "ancestor::m:mstack and not(ancestor::m:mlongdiv) and" |
341 | | - - "following-sibling::*[self::m:msline] and" |
342 | | - - "not(preceding-sibling::*[self::m:msline]) and" |
343 | | - - "not(*[self::m:none]) and not(*[self::m:mo][.='×']) and" |
344 | | - - "*[last()][self::m:mo] and (preceding-sibling::*[self::m:mn] or preceding-sibling::*[self::m:msrow])" |
345 | | - replace: |
346 | | - - x: "*[last()][self::m:mo]" |
347 | | - - x: "./*[self::m:mn]" |
348 | | - |
349 | | -- name: msrow-stack-leading-operator |
350 | | - tag: msrow |
351 | | - match: |
352 | | - - "ancestor::m:mstack and not(ancestor::m:mlongdiv) and" |
353 | | - - "following-sibling::*[self::m:msline] and" |
354 | | - - "not(preceding-sibling::*[self::m:msline]) and" |
355 | | - - "not(*[self::m:none]) and not(*[self::m:mo][.='×']) and" |
356 | | - - "*[1][self::m:mo] and (preceding-sibling::*[self::m:mn] or preceding-sibling::*[self::m:msrow])" |
357 | | - replace: |
358 | | - - x: "*[self::m:mo]" |
359 | | - - x: "./*[self::m:mn]" |
360 | | - |
361 | 338 | - name: msrow-stack-before-msline |
362 | 339 | tag: msrow |
363 | 340 | match: |
364 | | - - "ancestor::m:mstack and not(ancestor::m:mlongdiv) and" |
365 | | - - "following-sibling::*[self::m:msline] and" |
366 | | - - "not(preceding-sibling::*[self::m:msline]) and" |
367 | | - - "not(*[self::m:none]) and not(*[self::m:mo][.='×'])" |
368 | | - replace: |
369 | | - - x: "./*[self::m:mn]" |
370 | | - - test: |
371 | | - if: "*[self::m:mo] and following-sibling::*[self::m:msrow]" |
372 | | - then: [x: "*[self::m:mo]"] |
373 | | - |
374 | | -- name: msrow-operator-on-right |
375 | | - tag: msrow |
376 | | - match: "count(*) > 1 and *[last()][self::m:mo]" |
377 | | - replace: |
378 | | - - x: "*[last()]" |
379 | | - - x: "*[position()!=last()]" |
380 | | - |
381 | | -- name: msrow-default-zero-shift |
382 | | - tag: msrow |
383 | | - match: |
384 | | - - "number(IfThenElse(@data-position, @data-position, IfThenElse(@position, @position, 0)))=0" |
| 341 | + - "ancestor::m:mstack and not(ancestor::m:mlongdiv)" |
385 | 342 | variables: |
386 | | - - AfterMsline: "preceding-sibling::*[self::m:msline] or (preceding-sibling::*[self::m:msrow] and preceding-sibling::*[self::m:msrow]/preceding-sibling::*[self::m:msline])" |
387 | | - - BetweenMslines: "preceding-sibling::*[self::m:msline] and following-sibling::*[self::m:msline]" |
388 | 343 | - RowPos: "number(IfThenElse(@data-position, @data-position, IfThenElse(@position, @position, 0)))" |
389 | | - - IsLastPartialRow: "following-sibling::*[1][self::m:msline]" |
390 | | - - FollowingIsLastPartial: "following-sibling::*[1][self::m:msrow or self::m:mn][following-sibling::*[1][self::m:msline]]" |
391 | | - - FollowingRowPos: "number(IfThenElse(following-sibling::*[1]/@data-position, following-sibling::*[1]/@data-position, IfThenElse(following-sibling::*[1]/@position, following-sibling::*[1]/@position, 0)))" |
392 | | - - ShiftAmount: "IfThenElse($IsLastPartialRow, 0, IfThenElse($FollowingIsLastPartial, $FollowingRowPos, $RowPos + 1))" |
| 344 | + - Operator: "ancestor::m:mstack/@data-operator" |
393 | 345 | replace: |
394 | 346 | - test: |
395 | | - - if: "$BetweenMslines and $IsLastPartialRow" |
396 | | - then: |
397 | | - - x: "*" |
398 | | - - t: ";" |
399 | | - - else_if: "$BetweenMslines" |
| 347 | + - if: "$RowPos != 0" |
400 | 348 | then: |
401 | | - - x: "*" |
402 | | - - t: "," |
403 | | - - t: "shifted to the left" |
404 | | - - x: "$ShiftAmount" |
| 349 | + - pause: medium |
405 | 350 | - test: |
406 | | - if: "$ShiftAmount=1" |
407 | | - then: [t: "digit"] |
408 | | - else: [t: "digits"] |
409 | | - - test: |
410 | | - - if: "following-sibling::*[self::m:msrow or self::m:mn][following-sibling::*[self::m:msrow or self::m:mn]] or ./*[@data-elem-block-parts='true']" |
411 | | - then: [t: ";"] |
412 | | - - else_if: "$AfterMsline" |
413 | | - then: |
414 | | - - x: "*" |
415 | | - - t: ";" |
416 | | - - else: [x: "*"] |
417 | | - |
418 | | -- name: msrow-default-shifted |
419 | | - tag: msrow |
420 | | - match: |
421 | | - - "not(parent::*[self::m:mlongdiv]) and" |
422 | | - - "number(IfThenElse(@data-position, @data-position, IfThenElse(@position, @position, 0)))!=0" |
423 | | - variables: |
424 | | - - RowPos: "number(IfThenElse(@data-position, @data-position, IfThenElse(@position, @position, 0)))" |
425 | | - - AfterMsline: "preceding-sibling::*[self::m:msline] or (preceding-sibling::*[self::m:msrow] and preceding-sibling::*[self::m:msrow]/preceding-sibling::*[self::m:msline])" |
426 | | - - BetweenMslines: "preceding-sibling::*[self::m:msline] and following-sibling::*[self::m:msline]" |
427 | | - - IsLastPartialRow: "following-sibling::*[1][self::m:msline]" |
428 | | - - FollowingIsLastPartial: "following-sibling::*[1][self::m:msrow or self::m:mn][following-sibling::*[1][self::m:msline]]" |
429 | | - - FollowingRowPos: "number(IfThenElse(following-sibling::*[1]/@data-position, following-sibling::*[1]/@data-position, IfThenElse(following-sibling::*[1]/@position, following-sibling::*[1]/@position, 0)))" |
430 | | - - ShiftAmount: "IfThenElse($IsLastPartialRow, 0, IfThenElse($FollowingIsLastPartial, $FollowingRowPos, $RowPos + 1))" |
431 | | - replace: |
432 | | - - test: |
433 | | - - if: "$BetweenMslines and $IsLastPartialRow" |
434 | | - then: |
435 | | - - x: "*" |
436 | | - - t: ";" |
437 | | - - else_if: "$BetweenMslines" |
438 | | - then: |
439 | | - - x: "*" |
440 | | - - t: "," |
441 | | - - t: "shifted to the left" |
442 | | - - x: "$ShiftAmount" |
| 351 | + if: "$RowPos > 0" |
| 352 | + then: |
| 353 | + - t: "shifted to the left" |
| 354 | + - x: "$RowPos" |
| 355 | + else: |
| 356 | + - t: "shifted to the right" |
| 357 | + - x: "-$RowPos" |
443 | 358 | - test: |
444 | | - if: "$ShiftAmount=1" |
| 359 | + if: "$RowPos=1 or $RowPos=-1" |
445 | 360 | then: [t: "digit"] |
446 | 361 | else: [t: "digits"] |
447 | | - - test: |
448 | | - - if: "following-sibling::*[self::m:msrow or self::m:mn][following-sibling::*[self::m:msrow or self::m:mn]] or ./*[@data-elem-block-parts='true']" |
449 | | - then: [t: ";"] |
450 | | - - else_if: "$AfterMsline" |
| 362 | + - pause: short |
| 363 | + - x: "ElemMathRowDigits(.)" |
| 364 | + - test: |
| 365 | + # speak the operator if before the the first msline, but not after it or directly before it (1+2+3 equals ...) |
| 366 | + # if it is a multiplication problem, then the second chunk will be addition, but it won't be marked as such |
| 367 | + if: "$Operator and following-sibling::*[following-sibling::m:msline] and not(following-sibling::*[1][self::m:msline])" |
451 | 368 | then: |
452 | | - - x: "*" |
453 | | - - t: ";" |
454 | | - - else: |
455 | | - - pause: 500 |
456 | | - - t: "shifted to the left" |
457 | | - - x: "$RowPos" |
| 369 | + - pause: short |
458 | 370 | - test: |
459 | | - if: "$RowPos=1" |
460 | | - then: |
461 | | - - t: "digit" |
462 | | - - t: "," |
463 | | - else: [t: "digits"] |
464 | | - - x: "*" |
465 | | - - t: ";" |
| 371 | + if: "preceding-sibling::*[self::m:msline]" |
| 372 | + then: [x: "'+'"] # second chunk of multiplication problem |
| 373 | + else: [x: "$Operator"] |
| 374 | + - pause: short |
466 | 375 |
|
467 | 376 | - name: msline-default-zero |
468 | 377 | tag: msline |
469 | 378 | match: "number(IfThenElse(@data-position, @data-position, IfThenElse(@position, @position, 0)))=0" |
470 | 379 | replace: |
471 | 380 | - test: |
472 | 381 | - if: "not(following-sibling::*) and preceding-sibling::*[1][self::m:msrow][*[self::m:none]]" |
473 | | - then: [t: ";"] |
| 382 | + then: [pause: long] |
474 | 383 | - else: [pause: 200] |
475 | 384 | - t: "equals" |
476 | 385 | - test: |
477 | 386 | if: "following-sibling::*[1][self::m:mscarries]" |
478 | 387 | then: [pause: 200] |
479 | | - else: [t: ";"] |
| 388 | + else: [pause: long] |
480 | 389 |
|
481 | 390 | - name: msline-default-shifted |
482 | 391 | tag: msline |
|
541 | 450 | - name: none-in-mscarries |
542 | 451 | tag: none |
543 | 452 | match: |
544 | | - - "parent::*[self::m:mscarries] and count(following-sibling::*) > 0 and" |
545 | | - - "(../@crossout and ../@crossout!='none') or count(preceding-sibling::*)=0" |
| 453 | + - "parent::*[self::m:mscarries] and not(@data-changed='added') and count(following-sibling::*) > 0 and" |
| 454 | + - "(../@crossout and ../@crossout!='none') or (not(@data-changed='added') and count(preceding-sibling::*[not(@data-changed='added')])=0)" |
546 | 455 | variables: |
547 | 456 | - Column: "number(@data-elem-carry-column)" |
548 | 457 | replace: |
|
647 | 556 | - Operator: "ancestor::m:mstack/@data-operator" |
648 | 557 | replace: |
649 | 558 | - x: "*" |
| 559 | + # FIX: this is an AI-generated mess |
650 | 560 | - test: |
651 | 561 | - if: "following-sibling::*[1][self::m:mscarries] and ($Operator='-' or $Operator='−')" |
652 | | - then: [t: ";"] |
| 562 | + then: [pause: long] |
653 | 563 | - else_if: "following-sibling::*[1][self::m:mscarries] and $Operator='×'" |
654 | 564 | then: |
655 | 565 | - t: "next row" |
656 | | - - t: ";" |
| 566 | + - pause: long |
657 | 567 | - else_if: "@data-elem-carry-terminator='mscarry'" |
658 | 568 | then: [pause: 200] |
659 | 569 | - else_if: "@data-elem-carry-terminator='none' and ($Operator='-' or $Operator='−' or $Operator='+')" |
660 | | - then: [t: ";"] |
| 570 | + then: [pause: long] |
661 | 571 | - else_if: "($Operator='-' or $Operator='−') and not(following-sibling::*[1][self::m:mscarries])" |
662 | 572 | then: [pause: 200] |
663 | 573 | - else_if: "$Operator='×' and not(following-sibling::*[1][self::m:mscarries]) and (following-sibling::*[self::m:mn] or following-sibling::*[self::m:msrow])" |
664 | 574 | then: [pause: 200] |
665 | 575 | - else_if: "$Operator='×' and not(following-sibling::*[1][self::m:mscarries]) and not(following-sibling::*[self::m:mn] or following-sibling::*[self::m:msrow])" |
666 | | - then: [t: ";"] |
| 576 | + then: [pause: long] |
667 | 577 | - else: [pause: 200] |
668 | 578 |
|
669 | 579 | # --- per-digit mn in multi-column msrow --- |
|
673 | 583 | match: "parent::m:msrow and (ancestor::m:mstack or ancestor::m:mlongdiv) and @data-elem-column and not(@data-elem-whole='true')" |
674 | 584 | variables: |
675 | 585 | - Column: "number(@data-elem-column)" |
676 | | - - DecimalPoint: "@data-decimalpoint" |
| 586 | + - DecimalPoint: "parent::m:msrow/@data-decimalpoint" |
677 | 587 | - InLongdiv: "ancestor::m:mlongdiv" |
678 | 588 | replace: |
679 | 589 | - bookmark: "@id" |
| 590 | + # FIX: this seems like an AI-generated mess |
680 | 591 | - test: |
681 | 592 | - if: ".=',' and $DecimalPoint!=','" |
682 | 593 | then: [t: "comma"] |
|
687 | 598 | - else_if: ".!='.' or $DecimalPoint='.'" |
688 | 599 | then: [x: "translate(., $BlockSeparators, '')"] |
689 | 600 | - test: |
690 | | - - if: "not($InLongdiv)" |
691 | | - then: [] |
692 | | - - else: |
693 | | - - pause: 100 |
694 | | - - test: |
695 | | - - if: "not($InLongdiv)" |
696 | | - then: [] |
697 | | - - else_if: "$Column=-1" |
698 | | - then: [t: "decimal point"] |
699 | | - - else_if: "DefinitionValue(string($Column), 'Speech', 'ElemMathPlace') != ''" |
700 | | - then: |
701 | | - - t: "in the" |
702 | | - - x: "DefinitionValue(string($Column), 'Speech', 'ElemMathPlace')" |
703 | | - - t: "column" |
704 | | - - else: |
705 | | - - t: "in the ten to the" |
706 | | - - x: "$Column" |
707 | | - - t: "column" |
| 601 | + - if: "$InLongdiv" |
| 602 | + then: |
| 603 | + - pause: short |
| 604 | + - test: |
| 605 | + - if: "$Column=-1" |
| 606 | + then: [t: "decimal point"] |
| 607 | + - else_if: "DefinitionValue(string($Column), 'Speech', 'ElemMathPlace') != ''" |
| 608 | + then: |
| 609 | + - t: "in the" |
| 610 | + - x: "DefinitionValue(string($Column), 'Speech', 'ElemMathPlace')" |
| 611 | + - t: "column" |
| 612 | + - else: |
| 613 | + - t: "in the ten to the" |
| 614 | + - x: "$Column" |
| 615 | + - t: "column" |
0 commit comments